#if (FEATURE_MODE == 0)
/**
 @file sys_usw_dot1ae.c

 @date 2010-2-26

 @version v2.0

---file comments----
*/

/***************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "sal.h"
#include "ctc_error.h"
#include "ctc_hash.h"
#include "ctc_port.h"
#include "ctc_vector.h"
#include "ctc_linklist.h"
#include "ctc_spool.h"
#include "ctc_warmboot.h"

#include "sys_usw_chip.h"
#include "sys_usw_common.h"
#include "sys_usw_opf.h"
#include "sys_usw_dot1ae.h"
#include "sys_usw_port.h"
#include "sys_usw_vlan.h"
#include "sys_usw_scl_api.h"
#include "sys_usw_ftm.h"
#include "sys_usw_internal_port.h"
#include "sys_usw_qos_api.h"
#include "sys_usw_internal_port.h"
#include "sys_usw_nexthop_api.h"

#include "drv_api.h"
#include "sys_usw_wb_common.h"
#include "sys_usw_register.h"
#include "sys_usw_dmps.h"
#include "sys_usw_dma.h"
#include "sys_usw_nexthop.h"
#include "sys_usw_interrupt.h"
#include "sys_usw_mac.h"
/***************************************************************
 *
 *  Defines and Macros
 *
 ***************************************************************/

#define SYS_DOT1AE_BIND_CHANS_ON_ONE_PORT (-2)
#define SYS_DOT1AE_BIND_SAME_SCI_P2MP (-3)



/****************************************************************************
 *
* Global and Declaration
*
*****************************************************************************/

sys_dot1ae_master_t* usw_dot1ae_master[CTC_MAX_LOCAL_CHIP_NUM_PP] = {NULL};




/***************************************************************
 *
 *  Functions
 *
 ***************************************************************/

STATIC int32
_sys_usw_dot1ae_db_free_chan_node(sys_dot1ae_chan_t* p_sys_chan, void* user_data)
{
    sys_dot1ae_chan_bind_node_t* p_sec_chan_bind_node = NULL;
    ctc_slistnode_t        *node = NULL, *next_node = NULL;
    CTC_SLIST_LOOP_DEL(p_sys_chan->bind_mem_list, node, next_node)
    {
        p_sec_chan_bind_node = (sys_dot1ae_chan_bind_node_t*)node;
        mem_free(p_sec_chan_bind_node);
    }
    ctc_slist_free(p_sys_chan->bind_mem_list);

    if (p_sys_chan->key)
    {
        mem_free(p_sys_chan->key);
    }

    if (p_sys_chan->sci)
    {
        mem_free(p_sys_chan->sci);
    }
    mem_free(p_sys_chan->an_stats);
    mem_free(p_sys_chan->sa_cfg);

    mem_free(p_sys_chan);
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dot1ae_db_free_entry_node(void* node_data, void* user_data)
{
    mem_free(node_data);
    return CTC_E_NONE;
}


STATIC int32
_sys_usw_dot1ae_build_entry_hash_key(sys_dot1ae_entry_t* p_sys_dot1ae_entry)
{
    return ctc_hash_caculate(sizeof(p_sys_dot1ae_entry->entry_id), &(p_sys_dot1ae_entry->entry_id));
}

STATIC int32
_sys_usw_dot1ae_cmp_entry_hash(sys_dot1ae_entry_t* store_dot1ae_entry,sys_dot1ae_entry_t* lkup_dot1ae_entry)
{
    if (!store_dot1ae_entry || !lkup_dot1ae_entry)
    {
        return FALSE;
    }
    if (store_dot1ae_entry->entry_id == lkup_dot1ae_entry->entry_id)
    {
        return TRUE;
    }
    return FALSE;
}

 STATIC int32
 _sys_usw_dot1ae_build_chan_hash_key(sys_dot1ae_chan_t* p_sys_sec_chan)
 {
     return ctc_hash_caculate(sizeof(p_sys_sec_chan->chan_id), &(p_sys_sec_chan->chan_id));
 }

 STATIC int32
 _sys_usw_dot1ae_cmp_chan_hash(sys_dot1ae_chan_t* store_sys_chan,sys_dot1ae_chan_t* lkup_sys_chan)
 {
     if (!store_sys_chan || !lkup_sys_chan)
     {
         return FALSE;
     }
     if (store_sys_chan->chan_id == lkup_sys_chan->chan_id)
     {
         return TRUE;
     }
     return FALSE;
 }

int32 sys_usw_dot1ae_db_init(uint8 lchip)
{
    sys_usw_opf_t opf;
    ctc_spool_t spool;

    /*1.malloc db*/
    usw_dot1ae_master[lchip] = (sys_dot1ae_master_t*)mem_malloc(MEM_DOT1AE_MODULE, sizeof(sys_dot1ae_master_t));
    if (NULL == usw_dot1ae_master[lchip])
    {
        SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }
    sal_memset(usw_dot1ae_master[lchip], 0, sizeof(sys_dot1ae_master_t));

    /*2.creat hash db*/
    usw_dot1ae_master[lchip]->chan_hash = ctc_hash_create(((MCHIP_CAP(SYS_CAP_DOT1AE_SEC_CHAN_NUM)*2) / CTC_HASH_32_BLOCK_SIZE),
                                                          CTC_HASH_32_BLOCK_SIZE,
                                                          (hash_key_fn)_sys_usw_dot1ae_build_chan_hash_key,
                                                          (hash_cmp_fn)_sys_usw_dot1ae_cmp_chan_hash);
    if (NULL == usw_dot1ae_master[lchip]->chan_hash)
    {
        SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }

    /* Create xsec-flow entry hash for Arctic */
    if (DRV_FROM_AT(lchip))
    {
        usw_dot1ae_master[lchip]->entry_hash = ctc_hash_create(((MCHIP_CAP(SYS_CAP_DOT1AE_SEC_CHAN_NUM)*2) / CTC_HASH_32_BLOCK_SIZE),
                                                               CTC_HASH_32_BLOCK_SIZE,
                                                               (hash_key_fn)_sys_usw_dot1ae_build_entry_hash_key,
                                                               (hash_cmp_fn)_sys_usw_dot1ae_cmp_entry_hash);
        if (NULL == usw_dot1ae_master[lchip]->entry_hash)
        {
            return CTC_E_NO_MEMORY;
        }
    }

    /* Create spool for xsec hash sel in Arctic */
    if (DRV_FROM_AT(lchip))
    {
        sal_memset(&spool, 0, sizeof(ctc_spool_t));
        spool.lchip = lchip;
        spool.block_num = 1;
        spool.block_size = 15;
        spool.max_count = 15;
        spool.user_data_size = sizeof(sys_dot1ae_maskbmp_t);
        spool.key_size = CTC_OFFSET_OF(sys_dot1ae_maskbmp_t, calc_key_len);
        spool.min_index = 1;
        spool.max_index = 15;
        spool.desc = "dp0-rx-maskbmp";
        usw_dot1ae_master[lchip]->dp0_rx_spool = ctc_spool_create(&spool);
        if (NULL == usw_dot1ae_master[lchip]->dp0_rx_spool)
        {
            return CTC_E_NO_MEMORY;
        }
        spool.desc = "dp0-tx-maskbmp";
        usw_dot1ae_master[lchip]->dp0_tx_spool = ctc_spool_create(&spool);
        if (NULL == usw_dot1ae_master[lchip]->dp0_tx_spool)
        {
            return CTC_E_NO_MEMORY;
        }
        spool.desc = "dp1-rx-maskbmp";
        usw_dot1ae_master[lchip]->dp1_rx_spool = ctc_spool_create(&spool);
        if (NULL == usw_dot1ae_master[lchip]->dp1_rx_spool)
        {
            return CTC_E_NO_MEMORY;
        }
        spool.desc = "dp1-tx-maskbmp";
        usw_dot1ae_master[lchip]->dp1_tx_spool = ctc_spool_create(&spool);
        if (NULL == usw_dot1ae_master[lchip]->dp1_tx_spool)
        {
            return CTC_E_NO_MEMORY;
        }
    }

    /*3. opf init*/
    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    CTC_ERROR_RETURN(sys_usw_opf_init(lchip, &usw_dot1ae_master[lchip]->dot1ae_opf_type, DRV_FROM_TMM(lchip)? 4 : 2, "opf-dot1ae-chan"));
    opf.pool_type = usw_dot1ae_master[lchip]->dot1ae_opf_type;
    opf.pool_index = 0;      /*tx chan*/
    CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 0, MCHIP_CAP(SYS_CAP_DOT1AE_TX_CHAN_NUM)));
    opf.pool_index = 1;      /*rx chan*/
    CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 0, MCHIP_CAP(SYS_CAP_DOT1AE_RX_CHAN_NUM)));
    if (DRV_FROM_TMM(lchip))
    {
        opf.pool_index = 2;      /*DP1 tx chan*/
        CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 0, MCHIP_CAP(SYS_CAP_DOT1AE_TX_CHAN_NUM)));
        opf.pool_index = 3;      /*DP1 rx chan*/
        CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 0, MCHIP_CAP(SYS_CAP_DOT1AE_RX_CHAN_NUM)));
    }

    return CTC_E_NONE;
}


int32 sys_usw_dot1ae_db_deinit(uint8 lchip)
{
    ctc_hash_free2(usw_dot1ae_master[lchip]->chan_hash, (hash_traversal_fn)_sys_usw_dot1ae_db_free_chan_node, NULL);

    if (DRV_FROM_AT(lchip))
    {
        ctc_hash_free2(usw_dot1ae_master[lchip]->entry_hash, (hash_traversal_fn)_sys_usw_dot1ae_db_free_entry_node, NULL);
        ctc_spool_free(usw_dot1ae_master[lchip]->dp0_rx_spool);
        ctc_spool_free(usw_dot1ae_master[lchip]->dp0_tx_spool);
        ctc_spool_free(usw_dot1ae_master[lchip]->dp1_rx_spool);
        ctc_spool_free(usw_dot1ae_master[lchip]->dp1_tx_spool);
        if (!SYS_VCHIP_PP_IS_NOT_BASE(lchip))
        {
            sys_usw_com_entry_hash_deinit(lchip, usw_dot1ae_master[lchip]->pp_hash);/*use ctc_hash_free2*/
        }
    }
    return CTC_E_NONE;
}

sys_dot1ae_chan_t *
_sys_usw_dot1ae_chan_lookup(uint8 lchip, uint32 chan_id)
{
    sys_dot1ae_chan_t sec_chan;
    sys_dot1ae_chan_t* p_sys_chan = NULL;
    sal_memset(&sec_chan, 0, sizeof(sys_dot1ae_chan_t));
    sec_chan.chan_id = chan_id;
    p_sys_chan = ctc_hash_lookup(usw_dot1ae_master[lchip]->chan_hash, &sec_chan);
    return p_sys_chan;
}

STATIC int32
_sys_usw_dot1ae_chan_build_node(uint8 lchip, ctc_dot1ae_sc_t* p_sc, sys_dot1ae_chan_t* p_sys_sec_chan)
{
    uint32 size_an_stats = 0;
    p_sys_sec_chan->chan_id = p_sc->chan_id;
    p_sys_sec_chan->dir = p_sc->dir;
    p_sys_sec_chan->valid = 1;
    p_sys_sec_chan->p2mp = p_sc->is_p2mp;
    p_sys_sec_chan->pn_mode = p_sc->pn_mode;
    p_sys_sec_chan->clear_tag_en = p_sc->clear_tag_en;
    p_sys_sec_chan->with_ctc_sh = p_sc->with_ctc_sh;
    p_sys_sec_chan->bind_mem_list = ctc_slist_new();
    p_sys_sec_chan->is_xpn = p_sc->pn_mode? (p_sc->pn_mode == CTC_DOT1AE_SC_XPN_MODE? 1 : 0) : usw_dot1ae_master[lchip]->is_xpn;

    if (DRV_IS_DUET2(lchip))
    {
        uint8 key_len = CTC_DOT1AE_KEY_LEN / 2;

        if (p_sc->dir == CTC_DOT1AE_SC_DIR_RX)
        {
            p_sys_sec_chan->key = mem_malloc(MEM_DOT1AE_MODULE, key_len * MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM) * sizeof(uint8));
            if (!p_sys_sec_chan->key)
            {
                return CTC_E_NO_MEMORY;
            }
            sal_memset(p_sys_sec_chan->key, 0, key_len * MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM) * sizeof(uint8));
        }
    }

    /* TM_MX and Arctic support 2 sa per sec-chan  */
    p_sys_sec_chan->sa_cfg= mem_malloc(MEM_DOT1AE_MODULE, sizeof(sys_dot1ae_sa_config_t) * MCHIP_CAP(SYS_CAP_DOT1AE_SA_PER_CHAN));
    size_an_stats = DRV_FROM_AT(lchip)?sizeof(sys_at_dot1ae_an_stats_t):((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip))?sizeof(sys_tmm_dot1ae_an_stats_t):sizeof(sys_tm_dot1ae_an_stats_t));
    p_sys_sec_chan->an_stats = mem_malloc(MEM_DOT1AE_MODULE, size_an_stats * MCHIP_CAP(SYS_CAP_DOT1AE_STATS_PER_CHAN));

    if ((!p_sys_sec_chan->sa_cfg) || (!p_sys_sec_chan->an_stats))
    {
        goto error0;
    }
    sal_memset(p_sys_sec_chan->an_stats, 0 , size_an_stats * MCHIP_CAP(SYS_CAP_DOT1AE_STATS_PER_CHAN));
    sal_memset(p_sys_sec_chan->sa_cfg, 0 , sizeof(sys_dot1ae_sa_config_t) * MCHIP_CAP(SYS_CAP_DOT1AE_SA_PER_CHAN));

    return CTC_E_NONE;
error0:
    if(DRV_IS_DUET2(lchip) && p_sc->dir == CTC_DOT1AE_SC_DIR_RX)
    {
        mem_free(p_sys_sec_chan->key);
    }
    mem_free(p_sys_sec_chan->sa_cfg);
    mem_free(p_sys_sec_chan->an_stats);
    return CTC_E_NO_MEMORY;
}

STATIC void*
_sys_usw_dot1ae_chan_remove_db(uint8 lchip, sys_dot1ae_chan_t* p_sys_sec_chan)
{
    return ctc_hash_remove(usw_dot1ae_master[lchip]->chan_hash, (void*)p_sys_sec_chan);
}


STATIC int32
_sys_usw_dot1ae_chan_add_db(uint8 lchip, sys_dot1ae_chan_t* p_sys_sec_chan)
{
    return (NULL == ctc_hash_insert(usw_dot1ae_master[lchip]->chan_hash, (void*)p_sys_sec_chan))?CTC_E_NO_MEMORY:CTC_E_NONE;
}

STATIC int32
_sys_usw_dot1ae_traverse(sys_dot1ae_chan_t* p_sys_chan,void* user_data)
{
    uint8 lchip = 0;
    uint32 chan_id = 0;
    uint32 gport = 0;
    uint32 is_p2mp =0;
    ctc_slistnode_t        *node = NULL;
    sys_dot1ae_chan_t* sys_chan =NULL;
    sys_dot1ae_chan_bind_node_t* p_sec_chan_bind_node = NULL;
    sys_traverse_t* traversal_data = (sys_traverse_t *)user_data;
    sys_chan = (sys_dot1ae_chan_t*)traversal_data->data;
    lchip = (uint8)traversal_data->value3;

    gport = traversal_data->value1;
    chan_id = sys_chan->chan_id;
    is_p2mp =sys_chan->p2mp;
    if (CTC_SLISTCOUNT(p_sys_chan->bind_mem_list))
    {
        node = p_sys_chan->bind_mem_list->head;
        p_sec_chan_bind_node = _ctc_container_of(node, sys_dot1ae_chan_bind_node_t, head);
        if ((gport ==p_sec_chan_bind_node->value) && (chan_id != p_sys_chan->chan_id)
            && (!(p_sys_chan->p2mp &&is_p2mp))
            &&(p_sys_chan->dir ==sys_chan->dir))
        {
            traversal_data->value2= p_sys_chan->chan_id;
            return SYS_DOT1AE_BIND_CHANS_ON_ONE_PORT;
        }
        if (p_sys_chan->sci
            && sys_chan->sci
            && !sal_memcmp(p_sys_chan->sci, sys_chan->sci, SYS_DOT1AE_SCI_LEN)
            && (chan_id != p_sys_chan->chan_id)
            && (p_sys_chan->dir == sys_chan->dir)
            &&((p_sys_chan->p2mp &&is_p2mp)))
        {
            sal_memset(sys_chan->sci, 0, SYS_DOT1AE_SCI_LEN);
            return SYS_DOT1AE_BIND_SAME_SCI_P2MP;
        }
    }
    else if (!DRV_FROM_AT(lchip))
    {
        if (p_sys_chan->binded && (gport == p_sys_chan->gport) && (chan_id != p_sys_chan->chan_id) \
            && (!(p_sys_chan->p2mp &&is_p2mp)) && (p_sys_chan->dir ==sys_chan->dir) && !p_sys_chan->is_use_plain)
        {
            traversal_data->value2= p_sys_chan->chan_id;
            return SYS_DOT1AE_BIND_CHANS_ON_ONE_PORT;
        }
    }

    return CTC_E_NONE;
}


STATIC int32
_sys_usw_dot1ae_bind_update_to_db(uint8 lchip, sys_com_dot1ae_bind_sc_t* p_bind_sc, sys_dot1ae_chan_t* p_sys_chan)
{
    sys_dot1ae_chan_bind_node_t* p_sec_chan_bind_node = NULL;
    p_sec_chan_bind_node = mem_malloc(MEM_DOT1AE_MODULE, sizeof(sys_dot1ae_chan_bind_node_t));
    if (NULL == p_sec_chan_bind_node)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_sec_chan_bind_node, 0, sizeof(sys_dot1ae_chan_bind_node_t));
    p_sec_chan_bind_node->value = p_bind_sc->gport;

    /* For TM_MX and Arctic, to get dp-id using gport */
    if (DRV_FROM_TMM(lchip) && SYS_DOT1AE_BIND_TYPE_PORT == p_bind_sc->type)
    {
        p_sys_chan->gport = p_bind_sc->gport;
    }
    p_sys_chan->pp_id = lchip % SYS_PP_NUM(lchip);
    p_sys_chan->binded = 1;
    p_sys_chan->binding_type = p_bind_sc->type;
    ctc_slist_add_head(p_sys_chan->bind_mem_list, &(p_sec_chan_bind_node->head));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dot1ae_bind_param_check(uint8 lchip, sys_com_dot1ae_bind_sc_t* p_bind_sc, sys_dot1ae_chan_t* p_sys_chan)
{
    ctc_slistnode_t        *node = NULL;
    sys_dot1ae_chan_bind_node_t* p_sec_chan_bind_node = NULL;
    sys_traverse_t user_data;
    int32 ret =0;

    sal_memset(&user_data, 0 , sizeof(sys_traverse_t));
    if (p_sys_chan->dir != p_bind_sc->dir)
    {
        SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Direction is not match !!\n");
        return CTC_E_INVALID_CONFIG;
    }
    if (((SYS_DOT1AE_BIND_TYPE_LOGICPORT == p_bind_sc->type) && (p_sys_chan->dir == CTC_DOT1AE_SC_DIR_TX))
        || ((SYS_DOT1AE_BIND_TYPE_NEXTHOP == p_bind_sc->type) && (p_sys_chan->dir == CTC_DOT1AE_SC_DIR_RX)))
    {
        SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Cloudsec decrypt must bind to Rx channel and encrypt must bind to Tx channel\n");
        return CTC_E_INVALID_CONFIG;
    }
    if (!p_bind_sc->type && !SYS_GPORT_IS_NETWORK_PORT(p_bind_sc->gport))
    {
        return CTC_E_INVALID_CONFIG;
    }

    if (MCHIP_1AE(lchip)->chk_pp_id)
    {
        CTC_ERROR_RETURN(MCHIP_1AE(lchip)->chk_pp_id(lchip, p_sys_chan->chan_id));
    }

    if (DRV_FROM_AT(lchip))
    {
        if ((0 != p_bind_sc->type) || p_sys_chan->p2mp)
        {
            return CTC_E_NOT_SUPPORT;
        }
        if (CTC_SLISTCOUNT(p_sys_chan->bind_mem_list) || p_sys_chan->binded)
        {
            SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "chan_id:%u has been bound\n", p_sys_chan->chan_id);
            return CTC_E_INVALID_CONFIG;
        }
    }
    else
    {
        if (CTC_SLISTCOUNT(p_sys_chan->bind_mem_list))
        {
            if (0 == p_sys_chan->binding_type
                || p_sys_chan->binding_type != p_bind_sc->type)/*check macsec/p2mp*/
            {
                SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "chan_id:%u has been bound\n", p_sys_chan->chan_id);
                return CTC_E_INVALID_CONFIG;
            }
            else
            {
                CTC_SLIST_LOOP(p_sys_chan->bind_mem_list, node)
                {
                    p_sec_chan_bind_node = _ctc_container_of(node, sys_dot1ae_chan_bind_node_t, head);
                    if (p_sec_chan_bind_node->value == p_bind_sc->gport)/*check clousec*/
                    {
                        return CTC_E_EXIST;
                    }
                }
            }
        }
    }

    user_data.value1 = p_bind_sc->gport;
    user_data.value3 = lchip;
    user_data.data = (void*)p_sys_chan;
    ret = ctc_hash_traverse(usw_dot1ae_master[lchip]->chan_hash, (hash_traversal_fn)_sys_usw_dot1ae_traverse, (void *)&user_data);
    if ((user_data.value2 != 0) && (SYS_DOT1AE_BIND_CHANS_ON_ONE_PORT == ret))
    {
        SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "gport:0x%x has already been bound with chan_id:%u, dir:%u\n", p_bind_sc->gport, p_sys_chan->chan_id, p_bind_sc->dir);
        return CTC_E_INVALID_CONFIG;
    }
    else if (SYS_DOT1AE_BIND_SAME_SCI_P2MP == ret)
    {
        SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "p2mp can not be set the same sci for one port\n");
        return CTC_E_INVALID_CONFIG;
    }

    if (DRV_IS_TSINGMA(lchip) && p_bind_sc->dir == CTC_DOT1AE_SC_DIR_TX && p_bind_sc->type == 1)
    {
        uint32  aes_key_index = 0;
        uint32  cipher_mode = 0;
        uint32 cmd = 0;
        uint8 idx =0;
        for (idx = 0; idx < MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM); idx++)
        {
            if (CTC_IS_BIT_SET(p_sys_chan->an_valid, idx))
            {
                aes_key_index = (p_sys_chan->sc_index[0] << 2) + (idx & 0x3);
                cmd = DRV_IOR(DsDot1AeAesKey_t, DsDot1AeAesKey_cipherMode_f);
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, aes_key_index, cmd, &cipher_mode));
                if (cipher_mode == 1 || cipher_mode == 2)
                {
                    return CTC_E_INVALID_CONFIG;
                }
            }
        }
    }
    return CTC_E_NONE;
}


STATIC int32
_sys_usw_dot1ae_check_update_param(uint8 lchip, ctc_dot1ae_sc_t* p_sc, sys_dot1ae_chan_t* p_sys_sec_chan)
{
    uint32 an_bitmap =0;
    uint8 an_count =0;
    uint8 an =0;
    ctc_dot1ae_sa_t* p_sa = NULL;
    ctc_dot1ae_glb_cfg_t glb_cfg;

    switch(p_sc->property)
    {
    case CTC_DOT1AE_SC_PROP_AN_EN :
        an_bitmap = p_sc->data;

        CTC_MAX_VALUE_CHECK(an_bitmap, MCHIP_CAP(SYS_CAP_DOT1AE_MAX_AN_BITMAP));

        for(an = 0; an < MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM);an++)
        {
            if( CTC_IS_BIT_SET(an_bitmap,an))
            {
                an_count++;
            }
        }

        if(p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX && an_count > 1)
        {
            return CTC_E_INVALID_PARAM;
        }

        for (an = 0; an < MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM); an++)
        {
            if (CTC_IS_BIT_SET(an_bitmap, an) && !CTC_IS_BIT_SET(p_sys_sec_chan->an_valid, an))
            {
                return CTC_E_NOT_READY;
            }
        }
        break;
    case CTC_DOT1AE_SC_PROP_NEXT_AN:
        {
            if (DRV_FROM_TMM(lchip))
            {
                return CTC_E_NOT_SUPPORT;
            }
            if (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_RX || p_sc->data >= MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM) )
            {
                return CTC_E_INVALID_PARAM;
            }
            if (!CTC_IS_BIT_SET(p_sys_sec_chan->an_valid, p_sc->data))
            {
                return CTC_E_NOT_READY;
            }
        }
        break;
    case CTC_DOT1AE_SC_PROP_INCLUDE_SCI :
        if (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_RX)
        {
            return CTC_E_INVALID_PARAM;
        }
        break;
    case CTC_DOT1AE_SC_PROP_SCI :
        CTC_PTR_VALID_CHECK(p_sc->ext_data);
        break;
    case CTC_DOT1AE_SC_PROP_REPLAY_WINDOW_SIZE :
    case CTC_DOT1AE_SC_PROP_REPLAY_PROTECT_EN:
        if (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX)
        {
            return CTC_E_INVALID_PARAM;
        }
        break;
    case CTC_DOT1AE_SC_PROP_SA_CFG :
        p_sa = (ctc_dot1ae_sa_t*)p_sc->ext_data;

        CTC_PTR_VALID_CHECK(p_sa);
        CTC_MAX_VALUE_CHECK(p_sa->an, MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM) - 1);
        CTC_MAX_VALUE_CHECK(p_sa->validateframes, CTC_DOT1AE_VALIDFRAMES_STRICT);
        CTC_MAX_VALUE_CHECK(p_sa->confid_offset, CTC_DOT1AE_ENCRYPTION_OFFSET_50);

        if (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX && CTC_FLAG_ISSET(p_sa->upd_flag, CTC_DOT1AE_SA_FLAG_VALIDATEFRAMES))
        {
            return CTC_E_INVALID_CONFIG;
        }
        if(DRV_FROM_TMM(lchip))
        {
            if (CTC_FLAG_ISSET(p_sa->upd_flag, CTC_DOT1AE_SA_FLAG_ICV_ERROR_ACTION))
            {
                return CTC_E_NOT_SUPPORT;
            }
        }
        if (DRV_IS_DUET2(lchip))
        {
            CTC_MAX_VALUE_CHECK(p_sa->next_pn, 0xffffffff);
        }

        if (CTC_FLAG_ISSET(p_sa->upd_flag, CTC_DOT1AE_SA_FLAG_KEY))
        {
            if (DRV_IS_DUET2(lchip))
            {
                CTC_MAX_VALUE_CHECK(p_sa->cipher_suite, CTC_DOT1AE_CIPHER_SUITE_GCM_AES_128);
                if ((p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_RX))
                {
                    if (!p_sys_sec_chan->key)
                    {
                        return CTC_E_NO_MEMORY;
                    }
                }
            }
            else
            {
                if (p_sa->cipher_suite == CTC_DOT1AE_CIPHER_SUITE_GCM_AES_128 || 
                    p_sa->cipher_suite == CTC_DOT1AE_CIPHER_SUITE_GCM_AES_256)
                {
                    p_sys_sec_chan->is_xpn = 0;
                    p_sys_sec_chan->pn_mode = CTC_DOT1AE_SC_PN_MODE;
                }
                else if (p_sa->cipher_suite == CTC_DOT1AE_CIPHER_SUITE_GCM_AES_XPN_128 ||
                         p_sa->cipher_suite == CTC_DOT1AE_CIPHER_SUITE_GCM_AES_XPN_256)
                {
                    p_sys_sec_chan->is_xpn = 1;
                    p_sys_sec_chan->pn_mode = CTC_DOT1AE_SC_XPN_MODE;
                }
                else
                {
                    return CTC_E_INVALID_PARAM;
                }
            }
        }

        if (CTC_FLAG_ISSET(p_sa->upd_flag, CTC_DOT1AE_SA_FLAG_NEXT_PN))
        {
            CTC_ERROR_RETURN(sys_usw_dot1ae_get_global_cfg(lchip, &glb_cfg));
            if ((CTC_DOT1AE_SC_PN_MODE_NONE == p_sys_sec_chan->pn_mode && glb_cfg.is_xpn)
              ||(CTC_DOT1AE_SC_PN_MODE_NONE != p_sys_sec_chan->pn_mode && p_sys_sec_chan->is_xpn))
            {
                if (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX && glb_cfg.tx_xpn_thrd > 0)
                {
                    CTC_MAX_VALUE_CHECK(p_sa->next_pn, glb_cfg.tx_xpn_thrd);
                }
                if (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_RX && glb_cfg.rx_xpn_thrd > 0)
                {
                    CTC_MAX_VALUE_CHECK(p_sa->next_pn, glb_cfg.rx_xpn_thrd);
                }
            }
            else
            {
                if (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX && glb_cfg.tx_pn_thrd > 0)
                {
                    CTC_MAX_VALUE_CHECK(p_sa->next_pn, glb_cfg.tx_pn_thrd);
                }
                if (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_RX && glb_cfg.rx_pn_thrd > 0)
                {
                    CTC_MAX_VALUE_CHECK(p_sa->next_pn, glb_cfg.rx_pn_thrd);
                }
            }
        }

        if (CTC_FLAG_ISSET(p_sa->upd_flag, CTC_DOT1AE_SA_FLAG_ENCRYPTION))
        {
            if (!DRV_IS_DUET2(lchip))
            {
                if ((((CTC_SLISTCOUNT(p_sys_sec_chan->bind_mem_list) ||p_sys_sec_chan->binded) && (0 != p_sys_sec_chan->binding_type)) || p_sys_sec_chan->clear_tag_en ) /*cloud sec*/
                    && (CTC_DOT1AE_ENCRYPTION_OFFSET_0 != p_sa->confid_offset))
                {
                    return CTC_E_INVALID_CONFIG;
                }
            }
        }
        break;
    case CTC_DOT1AE_SC_PROP_PROTOCOL_MODE :
        if (DRV_FROM_AT(lchip))
        {
            CTC_MAX_VALUE_CHECK(p_sc->data, 1);
        }
        else
        {
            return CTC_E_NOT_SUPPORT;
        }
    default :
        break;
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dot1ae_get_bind_chan_traverse(sys_dot1ae_chan_t* p_sys_chan,void* user_data)
{
    uint32 gport = 0;
    ctc_slistnode_t        *node = NULL;
    sys_dot1ae_bind_chan_t* bind_chan =NULL;
    sys_dot1ae_chan_bind_node_t* p_sec_chan_bind_node = NULL;
    sys_traverse_t* traversal_data = (sys_traverse_t *)user_data;
    gport = traversal_data->value1;
    bind_chan = (sys_dot1ae_bind_chan_t*)traversal_data->data;
    if (CTC_SLISTCOUNT(p_sys_chan->bind_mem_list))
    {
        node = p_sys_chan->bind_mem_list->head;
        p_sec_chan_bind_node = _ctc_container_of(node, sys_dot1ae_chan_bind_node_t, head);
        if ((gport == p_sec_chan_bind_node->value)&&(p_sys_chan->dir == bind_chan->dir))
        {
            bind_chan->p_chan_id[bind_chan->count] = p_sys_chan->chan_id;
            bind_chan->p2mp = p_sys_chan->p2mp;
            bind_chan->count++;
        }
    }
    return CTC_E_NONE;
}


int32
sys_usw_dot1ae_get_bind_sec_chan(uint8 lchip, void* p_bind_sc)
{
    sys_com_dot1ae_bind_sc_t* p_bind_chan = NULL;
    sys_dot1ae_chan_t* p_sys_chan =NULL;
    sys_traverse_t user_data;
    sys_dot1ae_bind_chan_t bind_chan;

    SYS_DOT1AE_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_bind_sc);
    p_bind_chan = (sys_com_dot1ae_bind_sc_t*)p_bind_sc;

    if (0 == p_bind_chan->chan_id)
    {
        sal_memset(&bind_chan, 0 , sizeof(sys_dot1ae_bind_chan_t));
        sal_memset(&user_data, 0 , sizeof(sys_traverse_t));
        bind_chan.dir = p_bind_chan->dir;
        bind_chan.p_chan_id = p_bind_chan->p_chan_id;
        user_data.data = (void*)&bind_chan;
        user_data.value1 = p_bind_chan->gport;
        CTC_ERROR_RETURN(ctc_hash_traverse(usw_dot1ae_master[lchip]->chan_hash, (hash_traversal_fn)_sys_usw_dot1ae_get_bind_chan_traverse, (void *)&user_data));
        p_bind_chan->SecYP2MP = bind_chan.p2mp;
    }
    else
    {
        p_sys_chan = _sys_usw_dot1ae_chan_lookup(lchip,  p_bind_chan->chan_id);
        if (NULL == p_sys_chan ||CTC_SLISTCOUNT(p_sys_chan->bind_mem_list)==0)
        {
            return CTC_E_NOT_READY;
        }
        SYS_DOT1AE_FOREACH_DP_BEGIN(p_sys_chan->dp_bmp)
        p_bind_chan->sc_index = p_sys_chan->sc_index[dp_idx];
        p_bind_chan->clear_tag_en= p_sys_chan->clear_tag_en;
        p_bind_chan->gport = (_ctc_container_of(p_sys_chan->bind_mem_list->head, sys_dot1ae_chan_bind_node_t, head))->value;
        break;
        SYS_DOT1AE_FOREACH_DP_END
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dot1ae_get_sa_idx(uint8 lchip,uint8 an,void* p_sec_chan)
{
    int32 idx = 0;
    sys_dot1ae_chan_t* p_sys_sec_chan =NULL;
    p_sys_sec_chan = (sys_dot1ae_chan_t*)p_sec_chan;
    for (idx = 0; idx < 2; idx++)
    {
        if (CTC_IS_BIT_SET(p_sys_sec_chan->an_valid, an) && p_sys_sec_chan->sa_cfg[idx].an == an)
        {
            return idx;
        }
    }
    return CTC_E_NOT_EXIST;
}

int32
sys_usw_dot1ae_bind_sec_chan(uint8 lchip, void* p_bind_sc_v)
{
    int32 ret = CTC_E_NONE;
    uint32 update_flag = 0;
    uint8 sa_idx = 0, an = 0;
    sys_com_dot1ae_bind_sc_t* p_bind_sc = (sys_com_dot1ae_bind_sc_t*)p_bind_sc_v;
    sys_dot1ae_chan_t* p_sys_chan = NULL;
    sys_dot1ae_chan_bind_node_t* p_sec_chan_bind_node = NULL;
    ctc_slistnode_t* node = NULL;
    ctc_slistnode_t* next_node = NULL;

    SYS_DOT1AE_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_bind_sc);

    SYS_DOT1AE_LOCK(lchip);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_CHANNEL, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_CHAN_BIND_NODE, 1);
    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "bind_sec_chan,chan_id:%u: gport:0x%x dir:%u\n", p_bind_sc->chan_id, p_bind_sc->gport, p_bind_sc->dir);

    /*1.sec_chan lookup*/
    p_sys_chan = _sys_usw_dot1ae_chan_lookup(lchip,  p_bind_sc->chan_id);
    if(!p_sys_chan)
    {
       SYS_DOT1AE_UNLOCK(lchip);
       return CTC_E_NOT_EXIST;
    }
    /*2.param check*/
    CTC_ERROR_GOTO(_sys_usw_dot1ae_bind_param_check(lchip,p_bind_sc,p_sys_chan), ret,error_proc);

    /*3.add gport to db*/
    CTC_ERROR_GOTO(_sys_usw_dot1ae_bind_update_to_db(lchip,p_bind_sc,p_sys_chan), ret,error_proc1);
    if (CTC_SLISTCOUNT(p_sys_chan->bind_mem_list) > 1 && p_sys_chan->binding_type)
    {/* for cloudsec, when more than one nh-id or logic-port bind with one sec-chan, use one sc_index*/
        p_bind_sc->sc_index = p_sys_chan->sc_index[0];
        p_bind_sc->include_sci = p_sys_chan->include_sci;
        SYS_DOT1AE_UNLOCK(lchip);
        return CTC_E_NONE;
    }

    /*4. build sc index*/
    if (MCHIP_1AE(lchip)->build_sc_index)
    {
        CTC_ERROR_GOTO(MCHIP_1AE(lchip)->build_sc_index(lchip, p_sys_chan), ret,error_proc1);
    }

    /* 5. reset sec-chan cfg */
    if (MCHIP_1AE(lchip)->reset_sec_chan_cfg)
    {
        CTC_ERROR_GOTO(MCHIP_1AE(lchip)->reset_sec_chan_cfg(lchip, p_sys_chan), ret, error_proc1);
    }

    /* 6. add sc and sa config to asic*/
    if (MCHIP_1AE(lchip)->add_sc_to_asic)
    {
        CTC_ERROR_GOTO(MCHIP_1AE(lchip)->add_sc_to_asic(lchip, p_sys_chan), ret, error_proc1);
    }
    CTC_SET_FLAG(update_flag, (CTC_DOT1AE_SA_FLAG_NEXT_PN | CTC_DOT1AE_SA_FLAG_KEY | CTC_DOT1AE_SA_FLAG_ENCRYPTION |
     CTC_DOT1AE_SA_FLAG_ICV_ERROR_ACTION | CTC_DOT1AE_SA_FLAG_VALIDATEFRAMES));
    
    /* ICV_ERROR_ACTION and VALIDATEFRAMES are not for tx channel */
    if (p_sys_chan->dir == CTC_DOT1AE_SC_DIR_TX)
    {
        CTC_UNSET_FLAG(update_flag, (CTC_DOT1AE_SA_FLAG_ICV_ERROR_ACTION | CTC_DOT1AE_SA_FLAG_VALIDATEFRAMES));
    }

    for (an = 0; an < MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM); an++)
    {
        if (CTC_IS_BIT_SET(p_sys_chan->an_valid, an))
        {
            CTC_ERROR_GOTO((sa_idx = (DRV_FROM_TMM(lchip)?_sys_usw_dot1ae_get_sa_idx(lchip, an, p_sys_chan):an)),ret, error_proc1);
            CTC_ERROR_GOTO(MCHIP_1AE(lchip)->add_sa_to_asic(lchip, p_sys_chan, sa_idx, update_flag), ret, error_proc1);
        }
    }

    /* 7. set chan ctl */
    if (MCHIP_1AE(lchip)->set_chan_ctl)
    {
        CTC_ERROR_GOTO(MCHIP_1AE(lchip)->set_chan_ctl(lchip, p_sys_chan), ret, error_proc1);
    }

    /* For TM.MX and TM cloudsec, return sc index
     * For TM and duet2 Macsec, return include_sci and sc_index
     */
     p_bind_sc->sc_index = (p_sys_chan->dp_bmp&0x1)? p_sys_chan->sc_index[0] : p_sys_chan->sc_index[1];
    p_bind_sc->include_sci = p_sys_chan->include_sci;

    goto error_proc;

    error_proc1:
    p_sys_chan->pp_id = 0;
    CTC_SLIST_LOOP_DEL(p_sys_chan->bind_mem_list, node, next_node)
    {
        p_sec_chan_bind_node = _ctc_container_of(node, sys_dot1ae_chan_bind_node_t, head);
        if (p_sec_chan_bind_node->value == p_bind_sc->gport)
        {
            ctc_slist_delete_node(p_sys_chan->bind_mem_list, &(p_sec_chan_bind_node->head));
            mem_free(p_sec_chan_bind_node);
        }
    }
    p_sys_chan->binded = 0;
    p_sys_chan->binding_type = 0;

    error_proc:
    SYS_DOT1AE_UNLOCK(lchip);

    return ret;
}

int32
sys_usw_dot1ae_unbind_sec_chan(uint8 lchip, void* p_bind_sc_v)
{
    sys_com_dot1ae_bind_sc_t* p_bind_sc = p_bind_sc_v;
    SYS_DOT1AE_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_bind_sc);
    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "unbind_sec_chan,sc_index:%u: gport:0x%x dir:%u\n", p_bind_sc->sc_index, p_bind_sc->gport, p_bind_sc->dir);
    SYS_DOT1AE_LOCK(lchip);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_CHANNEL, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_CHAN_BIND_NODE, 1);

    if (MCHIP_1AE(lchip)->unbind_sec_chan)
    {
        CTC_ERROR_RETURN_WITH_UNLOCK(MCHIP_1AE(lchip)->unbind_sec_chan(lchip,p_bind_sc),usw_dot1ae_master[lchip]->sec_mutex);
    }

    SYS_DOT1AE_UNLOCK(lchip);
    return CTC_E_NONE;

}

STATIC int32
_sys_usw_dot1ae_lkup_sec_sa(uint8 lchip, sys_dot1ae_chan_t* p_sec_chan, ctc_dot1ae_sa_t* p_sa, uint8* sa_index)
{
    int32 count =0;
    int32 sa_idx_tmp =0;
    uint32 an_bmp_tmp = 0;
    uint8 tmp_an = 0;

    an_bmp_tmp = p_sec_chan->an_en? p_sec_chan->an_en : p_sec_chan->an_valid;
    if (p_sec_chan->an_en && (!(p_sec_chan->an_en&(1<<p_sa->an))))
    {
        p_sec_chan->an_valid = 0;
        CTC_BIT_SET(p_sec_chan->an_valid, p_sa->an);
        p_sec_chan->an_valid |= p_sec_chan->an_en;
    }
    CTC_BMP_COUNT(an_bmp_tmp, count, 0, 8);
    sa_idx_tmp = _sys_usw_dot1ae_get_sa_idx(lchip, p_sa->an, p_sec_chan);

    /*check support cfg 2 sa in one sec-chan mostly*/
    if ((count == 2) && (sa_idx_tmp == CTC_E_NOT_EXIST))
    {
        CTC_BIT_UNSET(p_sec_chan->an_valid, p_sa->an);
        SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Only support cfg 2 sa in one sec-chan mostly\n");
        return CTC_E_INVALID_CONFIG;
    }
    else if((count == 1) && (sa_idx_tmp == CTC_E_NOT_EXIST)&&(p_sec_chan->an_en))
    {
        while(!CTC_IS_BIT_SET(p_sec_chan->an_en, tmp_an))tmp_an++;
        sa_idx_tmp = _sys_usw_dot1ae_get_sa_idx(lchip, tmp_an, p_sec_chan);
        *sa_index = !sa_idx_tmp;
    }
    else if ((count == 1) && (sa_idx_tmp == CTC_E_NOT_EXIST)&&(!p_sec_chan->an_en))
    {
        *sa_index = 1;
    }
    else if (count == 0)
    {
        *sa_index = 0;
    }
    else
    {
        *sa_index = sa_idx_tmp;
    }

    return CTC_E_NONE;

}

int32
sys_usw_dot1ae_add_sec_chan(uint8 lchip, ctc_dot1ae_sc_t* p_sc)
{
    int32  ret = CTC_E_NONE;
    sys_dot1ae_chan_t* p_sys_sec_chan = NULL;
    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /*1.param check*/
    SYS_DOT1AE_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_sc);
    CTC_MAX_VALUE_CHECK(p_sc->dir, CTC_DOT1AE_SC_DIR_RX);
    CTC_MIN_VALUE_CHECK(p_sc->chan_id, 1);
    CTC_MAX_VALUE_CHECK(p_sc->pn_mode, (DRV_FROM_TMM(lchip))? CTC_DOT1AE_SC_XPN_MODE : CTC_DOT1AE_SC_PN_MODE_NONE);
    if (p_sc->clear_tag_en && DRV_FROM_AT(lchip))
    {
        return CTC_E_NOT_SUPPORT;
    }
    SYS_DOT1AE_LOCK(lchip);

    /*2.sec_chan lookup*/
    p_sys_sec_chan = _sys_usw_dot1ae_chan_lookup(lchip,  p_sc->chan_id);
    if(p_sys_sec_chan)
    {
       SYS_DOT1AE_UNLOCK(lchip);
       return CTC_E_EXIST;
    }

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_CHANNEL, 1);

    /*3. build node, alloc memory for db*/
    p_sys_sec_chan = mem_malloc(MEM_DOT1AE_MODULE, sizeof(sys_dot1ae_chan_t));
    if (p_sys_sec_chan == NULL)
    {
        SYS_DOT1AE_UNLOCK(lchip);
        return CTC_E_NO_MEMORY;
    }
    else
    {
        sal_memset(p_sys_sec_chan,0,sizeof(sys_dot1ae_chan_t));
    }
    CTC_ERROR_GOTO(_sys_usw_dot1ae_chan_build_node(lchip,p_sc,p_sys_sec_chan),ret,error_proc);

    /*4. add to db*/
    CTC_ERROR_GOTO(_sys_usw_dot1ae_chan_add_db(lchip,p_sys_sec_chan),ret,error_proc);

    SYS_DOT1AE_UNLOCK(lchip);
    return CTC_E_NONE;

    error_proc:
    /* free memroy alloced in building node */
    if (p_sys_sec_chan->key)
    {
        mem_free(p_sys_sec_chan->key);
    }
    ctc_slist_free(p_sys_sec_chan->bind_mem_list);
    mem_free(p_sys_sec_chan->sa_cfg);
    mem_free(p_sys_sec_chan->an_stats);
    mem_free(p_sys_sec_chan);

    SYS_DOT1AE_UNLOCK(lchip);
    return ret;
}
sys_dot1ae_entry_t*
sys_usw_dot1ae_lkup_entry(uint8 lchip,uint32 entry_id)
{
    sys_dot1ae_entry_t sec_entry;
    sys_dot1ae_entry_t* p_sys_sec_entry =NULL;
    sal_memset(&sec_entry,0,sizeof(sys_dot1ae_entry_t));
    sec_entry.entry_id = entry_id;
    p_sys_sec_entry = ctc_hash_lookup(usw_dot1ae_master[lchip]->entry_hash, &sec_entry);
    return p_sys_sec_entry;
}

STATIC int32
_sys_usw_dot1ae_clear_entry(sys_dot1ae_entry_t* p_sys_entry,void* user_data)
{
    uint32 lchip = ((sys_traverse_t*)user_data)->value1;
    uint32 chan_id = ((sys_traverse_t*)user_data)->value2;
    uint32 entry_id = p_sys_entry->entry_id;
    sys_com_entry_hash_t* p_dot1ae_pp = NULL;

    if (p_sys_entry->chan_id == chan_id && MCHIP_1AE(lchip)->remove_entry)
    {
        /* remove entry on this sec-chan */
        MCHIP_1AE(lchip)->remove_entry(lchip, p_sys_entry->entry_id);

        /* remove entry from ctc layer entry_hash_db */
        if (NULL != (p_dot1ae_pp = sys_usw_com_lookup_entry_hash(lchip, usw_dot1ae_master[lchip]->entry_hash_db, entry_id)))
        {
            sys_usw_com_remove_entry_hash(lchip, usw_dot1ae_master[lchip]->entry_hash_db, p_dot1ae_pp);
        }
    }

    return CTC_E_NONE;
}

int32
sys_usw_dot1ae_remove_sec_chan(uint8 lchip,  ctc_dot1ae_sc_t* p_sc)
{
    int32 ret = CTC_E_NONE;
    sys_dot1ae_chan_t* p_sys_sec_chan = NULL;
    sys_dot1ae_chan_bind_node_t* p_sec_chan_bind_node = NULL;
    ctc_slistnode_t        *node = NULL, *next_node = NULL;
    sys_traverse_t user_data;
    sal_memset(&user_data, 0 , sizeof(sys_traverse_t));

    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_DOT1AE_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_sc);

    SYS_DOT1AE_LOCK(lchip);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_CHANNEL, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_CHAN_BIND_NODE, 1);

    /*1.lookup sc_chan*/
    p_sys_sec_chan = _sys_usw_dot1ae_chan_lookup(lchip,  p_sc->chan_id);
    if(!p_sys_sec_chan)
    {
        SYS_DOT1AE_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }

    /*2.unbind sec chan*/
    if (MCHIP_1AE(lchip)->unbind_sec_chan)
    {
        sys_com_dot1ae_bind_sc_t bind_sc;
        sal_memset(&bind_sc, 0, sizeof(bind_sc));
        bind_sc.type = 0;
        bind_sc.gport = SYS_RSV_PORT_DROP_ID;
        bind_sc.dir = p_sys_sec_chan->dir;
        bind_sc.chan_id = p_sys_sec_chan->chan_id;
        MCHIP_1AE(lchip)->unbind_sec_chan(lchip,&bind_sc);
    }
    /* for arctic, clear entry binded on this sec-chan */
    if (DRV_FROM_AT(lchip))
    {
        user_data.value1 = lchip;
        user_data.value2 = p_sc->chan_id;
        SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_ENTRY, 1);
        ctc_hash_traverse_remove(usw_dot1ae_master[lchip]->entry_hash, (hash_traversal_fn)_sys_usw_dot1ae_clear_entry, (void *)&user_data);
    }

    /*3.free node of p_sys_sec_chan*/
    CTC_SLIST_LOOP_DEL(p_sys_sec_chan->bind_mem_list, node, next_node)
    {
        p_sec_chan_bind_node = (sys_dot1ae_chan_bind_node_t*)node;
        mem_free(p_sec_chan_bind_node);
    }
    ctc_slist_free(p_sys_sec_chan->bind_mem_list);
    if(p_sys_sec_chan->key)
    {
        mem_free(p_sys_sec_chan->key);
    }
    if(p_sys_sec_chan->sci)
    {
        mem_free(p_sys_sec_chan->sci);
    }
    mem_free(p_sys_sec_chan->an_stats);
    mem_free(p_sys_sec_chan->sa_cfg);

    /*4.remove from db*/
    _sys_usw_dot1ae_chan_remove_db(lchip,p_sys_sec_chan);


    mem_free(p_sys_sec_chan);
    SYS_DOT1AE_UNLOCK(lchip);

    return ret;
}

STATIC int32
_sys_usw_dot1ae_set_sa_cfg(uint8 lchip, sys_dot1ae_chan_t *p_sc_info,ctc_dot1ae_sa_t* p_sa)
{
    uint32 key_len = CTC_DOT1AE_KEY_LEN;
    uint8 sa_idx;

    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /* get sa idx in db */
    if(DRV_FROM_TMM(lchip))
    {
        CTC_ERROR_RETURN(_sys_usw_dot1ae_lkup_sec_sa(lchip, p_sc_info, p_sa, &sa_idx));
    }
    else
    {
        sa_idx = p_sa->an;
    }

    CTC_BIT_SET(p_sc_info->an_valid, p_sa->an);
    p_sc_info->sa_cfg[sa_idx].an = p_sa->an;
    if(CTC_FLAG_ISSET(p_sa->upd_flag,CTC_DOT1AE_SA_FLAG_ENCRYPTION))
    {
        if (((CTC_SLISTCOUNT(p_sc_info->bind_mem_list) || p_sc_info->binded) && (0 != p_sc_info->binding_type)) || p_sc_info->clear_tag_en)
        {
            if (p_sa->no_encryption)
            {
                p_sc_info->sa_cfg[sa_idx].cipher_mode = SYS_DOT1AE_ICV_CAL_OFFSET_FROM_TAG;
                p_sc_info->sa_cfg[sa_idx].ebit_cbit = 0;
            }
            else
            {
                p_sc_info->sa_cfg[sa_idx].cipher_mode = SYS_DOT1AE_ENCRYPT_OFFSET_FROM_TAG;
                p_sc_info->sa_cfg[sa_idx].ebit_cbit = 1;
            }
        }
        else if (p_sa->no_encryption)
        {
            p_sc_info->sa_cfg[sa_idx].cipher_mode = SYS_DOT1AE_ICV_CAL_OFFSET_0;
            p_sc_info->sa_cfg[sa_idx].ebit_cbit = 0;
        }
        else if (p_sa->confid_offset == CTC_DOT1AE_ENCRYPTION_OFFSET_0)
        {
            p_sc_info->sa_cfg[sa_idx].cipher_mode = SYS_DOT1AE_ENCRYPT_OFFSET_0;
            p_sc_info->sa_cfg[sa_idx].ebit_cbit = 1;
        }
        else if (p_sa->confid_offset == CTC_DOT1AE_ENCRYPTION_OFFSET_30)
        {
            p_sc_info->sa_cfg[sa_idx].cipher_mode = SYS_DOT1AE_ENCRYPT_OFFSET_30;
            p_sc_info->sa_cfg[sa_idx].ebit_cbit = 1;
        }
        else if (p_sa->confid_offset == CTC_DOT1AE_ENCRYPTION_OFFSET_50)
        {
            p_sc_info->sa_cfg[sa_idx].cipher_mode = SYS_DOT1AE_ENCRYPT_OFFSET_50;
            p_sc_info->sa_cfg[sa_idx].ebit_cbit = 1;
        }
    }

    if (CTC_FLAG_ISSET(p_sa->upd_flag, CTC_DOT1AE_SA_FLAG_VALIDATEFRAMES))
    {
        if (DRV_IS_TSINGMA(lchip))
        {
            p_sc_info->sa_cfg[sa_idx].icv_discard = (p_sa->validateframes != CTC_DOT1AE_VALIDFRAMES_DISABLE);
            p_sc_info->sa_cfg[sa_idx].validateFrames = p_sa->validateframes;
            /*modify for validateframes equal zero, must check error, bug：106218*/
            if (CTC_DOT1AE_VALIDFRAMES_DISABLE == p_sa->validateframes)
            {
                p_sc_info->sa_cfg[sa_idx].validateFrames = 3;
            }
        }
        else if (DRV_FROM_TMM(lchip))
        {
            p_sc_info->validateFrames = p_sa->validateframes;
        }
    }
    /*icv err action for duet2*/
    if ((DRV_IS_DUET2(lchip))  && CTC_FLAG_ISSET(p_sa->upd_flag, CTC_DOT1AE_SA_FLAG_ICV_ERROR_ACTION)
        && p_sc_info->dir == CTC_DOT1AE_SC_DIR_RX)
    {
        /*icv check mode*/
        switch (p_sa->icv_error_action)
        {
            case CTC_EXCP_NORMAL_FWD:
                p_sc_info->sa_cfg[sa_idx].icv_discard = 0;
                p_sc_info->sa_cfg[sa_idx].icv_exception = 0;
                p_sc_info->sa_cfg[sa_idx].validateFrames = 1;
                break;
            case CTC_EXCP_FWD_AND_TO_CPU:
                p_sc_info->sa_cfg[sa_idx].icv_discard = 0;
                p_sc_info->sa_cfg[sa_idx].icv_exception = 1;
                p_sc_info->sa_cfg[sa_idx].validateFrames = 1;
                break;
            case CTC_EXCP_DISCARD_AND_TO_CPU:
                p_sc_info->sa_cfg[sa_idx].icv_discard = 1;
                p_sc_info->sa_cfg[sa_idx].icv_exception = 1;
                p_sc_info->sa_cfg[sa_idx].validateFrames = 2;
                break;
            case CTC_EXCP_DISCARD:
                p_sc_info->sa_cfg[sa_idx].icv_discard = 1;
                p_sc_info->sa_cfg[sa_idx].icv_exception = 0;
                p_sc_info->sa_cfg[sa_idx].validateFrames = 2;
                break;
            default:
                return CTC_E_INVALID_PARAM;
        }
    }
    /*set next pn*/
    if(CTC_FLAG_ISSET(p_sa->upd_flag,CTC_DOT1AE_SA_FLAG_NEXT_PN))
    {
        p_sc_info->sa_cfg[sa_idx].next_pn = p_sa->next_pn;
        if (p_sc_info->dir == CTC_DOT1AE_SC_DIR_RX)
        {
            if (p_sc_info->replayProtect)
            {
                p_sc_info->sa_cfg[sa_idx].lowest_pn = p_sa->next_pn > p_sc_info->replayProtectWindow ? p_sa->next_pn - p_sc_info->replayProtectWindow : 0;
            }
            else
            {
                p_sc_info->sa_cfg[sa_idx].lowest_pn = p_sa->next_pn;
            }
        }
    }
    /*set sa key*/
    if(CTC_FLAG_ISSET(p_sa->upd_flag,CTC_DOT1AE_SA_FLAG_KEY))
    {
        if ((p_sc_info->dir == CTC_DOT1AE_SC_DIR_RX) && DRV_IS_DUET2(lchip))
        {
            if (p_sa->key[0] != '\0')
            {
                sal_memcpy((uint8 *)p_sc_info->key + p_sa->an * (key_len / 2), (uint8 *)p_sa->key, (key_len / 2) * sizeof(uint8));
                SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "rx_key:(%s) \n", (p_sc_info->key + p_sa->an * (key_len / 2)));
            }
        }
        SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "key:(%s) \n", (p_sa->key));
        p_sc_info->sa_cfg[sa_idx].ssci = p_sa->ssci;
        p_sc_info->sa_cfg[sa_idx].cipher_suite = p_sa->cipher_suite;
        sal_memcpy(p_sc_info->sa_cfg[sa_idx].salt, p_sa->salt, CTC_DOT1AE_SALT_LEN);
        sal_memcpy(p_sc_info->sa_cfg[sa_idx].key, p_sa->key, CTC_DOT1AE_KEY_LEN);
    }

    /*if current sec-chan is binded, add sa cfg to asic*/
    if (CTC_SLISTCOUNT(p_sc_info->bind_mem_list) || p_sc_info->binded)
    {
        SYS_DOT1AE_FOREACH_DP_BEGIN(p_sc_info->dp_bmp)
        p_sc_info->dp_id = dp_idx;
        CTC_ERROR_RETURN(MCHIP_1AE(lchip)->add_sa_to_asic(lchip, p_sc_info, sa_idx, p_sa->upd_flag));
        SYS_DOT1AE_FOREACH_DP_END
    }
    return CTC_E_NONE;
}


int32
sys_usw_dot1ae_update_sec_chan(uint8 lchip, ctc_dot1ae_sc_t* p_sc)
{
    uint32 gport = 0;
    int32  ret = CTC_E_NONE;
    sys_dot1ae_chan_t* p_sys_sec_chan = NULL;

    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_DOT1AE_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_sc);

    SYS_DOT1AE_LOCK(lchip);

    /*1.lookup sc chan*/
    p_sys_sec_chan = _sys_usw_dot1ae_chan_lookup(lchip,  p_sc->chan_id);
    if(!p_sys_sec_chan)
    {
        SYS_DOT1AE_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }

    /*2. sc chan param check*/
    CTC_ERROR_GOTO(_sys_usw_dot1ae_check_update_param(lchip, p_sc,p_sys_sec_chan), ret, error_proc);

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_CHANNEL, 1);

    /*3. update sc and sa config */
    if (CTC_DOT1AE_SC_PROP_SA_CFG == p_sc->property)
    {
        CTC_ERROR_GOTO(_sys_usw_dot1ae_set_sa_cfg(lchip,p_sys_sec_chan,(ctc_dot1ae_sa_t*)p_sc->ext_data), ret, error_proc);
    }
    else
    {
        if (CTC_DOT1AE_SC_PROP_SCI == p_sc->property && !p_sys_sec_chan->sci)
        {
            p_sys_sec_chan->sci = mem_malloc(MEM_DOT1AE_MODULE, SYS_DOT1AE_SCI_LEN);
            if (NULL == p_sys_sec_chan->sci)
            {
                SYS_DOT1AE_UNLOCK(lchip);
                return CTC_E_NO_MEMORY;
            }
        }
        CTC_ERROR_GOTO(MCHIP_1AE(lchip)->update_sc_chan(lchip, p_sys_sec_chan, p_sc),ret,error_proc);
    }

    gport = p_sys_sec_chan->gport;

error_proc:
    SYS_DOT1AE_UNLOCK(lchip);

    if((DRV_IS_TSINGMA(lchip) || DRV_IS_DUET2(lchip)) && (ret == CTC_E_NONE) &&\
        (p_sc->property == CTC_DOT1AE_SC_PROP_INCLUDE_SCI))
    {
        CTC_ERROR_RETURN(sys_usw_port_api_set_internal_property(lchip, gport, SYS_PORT_PROP_DOT1AE_TX_SCI_EN, p_sc->data));
    }
    
    return ret;
}

STATIC int32
_sys_usw_dot1ae_get_sa_cfg(uint8 lchip, sys_dot1ae_chan_t *p_sc_info, ctc_dot1ae_sa_t* p_sa)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    int32 sa_idx = 0;
    uint16 key_index = 0;
    uint32 val_ary[2] = {0};

    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    CTC_MAX_VALUE_CHECK(p_sa->an, (MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM) - 1));

    /* 1. get sa idx from db */
    if(DRV_FROM_TMM(lchip))
    {
        CTC_ERROR_RETURN(sa_idx = _sys_usw_dot1ae_get_sa_idx(lchip, p_sa->an, p_sc_info));
    }
    else
    {
        sa_idx = p_sa->an;
    }

    /* 2. set sa cfg in p_sa */

    /* next pn will be updated by chip, so read from table if binded, or from db*/
    if (CTC_SLISTCOUNT(p_sc_info->bind_mem_list) || p_sc_info->binded)
    {
        SYS_DOT1AE_FOREACH_DP_BEGIN(p_sc_info->dp_bmp)
        key_index =(p_sc_info->sc_index[dp_idx] << 2) + (p_sa->an & 0x3);
        if (DRV_FROM_AT(lchip))
        {
            /*next_pn*/
            key_index = (p_sc_info->sc_index[dp_idx] << 1) + (sa_idx & 0x1);
            cmd = (p_sc_info->dir == CTC_DOT1AE_SC_DIR_TX) ? DRV_IOR(DsXSecEncryptSaStatus_t, DsXSecEncryptSaStatus_xpn_f):
            DRV_IOR(DsXSecDecryptSaStatus_t, DsXSecDecryptSaStatus_nextPn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, key_index, DRV_CMD_DP_EN(cmd,dp_idx), &val_ary));
            p_sa->next_pn = ((uint64)val_ary[1] << 32) | val_ary[0];
        }
        else if ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)))
        {
            /*next_pn*/
            key_index =(p_sc_info->sc_index[dp_idx] << 1) + (sa_idx & 0x1)+(dp_idx?MCHIP_CAP(SYS_CAP_DOT1AE_SEC_CHAN_NUM):0);
            cmd = (p_sc_info->dir == CTC_DOT1AE_SC_DIR_TX) ? DRV_IOR(DsMacsecTransmitSaPn_t, DsMacsecTransmitSaPn_macsecPn_f):
            DRV_IOR(DsMacsecReceiveSaStatus_t, DsMacsecReceiveSaStatus_nextPn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, key_index, cmd, &val_ary));
            p_sa->next_pn = ((uint64)val_ary[1]<<32) | val_ary[0];
        }
        else
        {
            /*next_pn*/
            key_index = (p_sc_info->sc_index[0]<< 2) + (p_sa->an & 0x3);
            cmd = (p_sc_info->dir == CTC_DOT1AE_SC_DIR_TX) ? DRV_IOR(DsEgressDot1AePn_t, DsEgressDot1AePn_pn_f)
            : DRV_IOR(DsDot1AePnCheck_t, DsDot1AePnCheck_nextPn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, key_index, cmd, &val_ary));
            p_sa->next_pn = ((uint64)val_ary[1]<<32) | val_ary[0];
        }
        SYS_DOT1AE_FOREACH_DP_END
    }
    else
    {
        p_sa->next_pn = p_sc_info->sa_cfg[sa_idx].next_pn;
    }

    if (p_sc_info->replayProtect)
    {
        p_sa->lowest_pn = (p_sa->next_pn > p_sc_info->replayProtectWindow)? (p_sa->next_pn - p_sc_info->replayProtectWindow) : 1;
    }
    else
    {
        p_sa->lowest_pn = p_sa->next_pn;
    }

    p_sa->in_use = CTC_IS_BIT_SET(p_sc_info->an_en, p_sa->an);
    sal_memcpy(p_sa->key, p_sc_info->sa_cfg[sa_idx].key, CTC_DOT1AE_KEY_LEN);
    p_sa->no_encryption = (p_sc_info->sa_cfg[sa_idx].cipher_mode == SYS_DOT1AE_ICV_CAL_OFFSET_0
                        || p_sc_info->sa_cfg[sa_idx].cipher_mode == SYS_DOT1AE_ICV_CAL_OFFSET_FROM_TAG)?1:0;
    p_sa->confid_offset = (p_sc_info->sa_cfg[sa_idx].cipher_mode == SYS_DOT1AE_ENCRYPT_OFFSET_30?CTC_DOT1AE_ENCRYPTION_OFFSET_30:\
                           (p_sc_info->sa_cfg[sa_idx].cipher_mode == SYS_DOT1AE_ENCRYPT_OFFSET_50?CTC_DOT1AE_ENCRYPTION_OFFSET_50:CTC_DOT1AE_ENCRYPTION_OFFSET_0));
    if (DRV_IS_DUET2(lchip))
    {
        if (p_sc_info->sa_cfg[sa_idx].icv_discard && p_sc_info->sa_cfg[sa_idx].icv_exception)
        {
            p_sa->icv_error_action = CTC_EXCP_DISCARD_AND_TO_CPU;
        }
        else if (!p_sc_info->sa_cfg[sa_idx].icv_discard && p_sc_info->sa_cfg[sa_idx].icv_exception)
        {
            p_sa->icv_error_action = CTC_EXCP_FWD_AND_TO_CPU;
        }
        else if (!p_sc_info->sa_cfg[sa_idx].icv_discard && !p_sc_info->sa_cfg[sa_idx].icv_exception)
        {
            p_sa->icv_error_action = CTC_EXCP_NORMAL_FWD;
        }
        else
        {
            p_sa->icv_error_action  = CTC_EXCP_DISCARD;
        }
    }
    p_sa->cipher_suite = p_sc_info->sa_cfg[sa_idx].cipher_suite;
    sal_memcpy(p_sa->salt, p_sc_info->sa_cfg[sa_idx].salt, CTC_DOT1AE_SALT_LEN);
    p_sa->ssci = p_sc_info->sa_cfg[sa_idx].ssci;
    
    if(DRV_IS_TSINGMA(lchip) && (0 == p_sc_info->sa_cfg[sa_idx].icv_discard))
    {
        p_sa->validateframes = CTC_DOT1AE_VALIDFRAMES_DISABLE;
    }
    else
    {
        p_sa->validateframes = DRV_IS_TSINGMA(lchip) ? p_sc_info->sa_cfg[sa_idx].validateFrames : p_sc_info->validateFrames;
    }

    return ret;
}

int32
sys_usw_dot1ae_get_sec_chan(uint8 lchip, ctc_dot1ae_sc_t* p_sc)
{
    int32  ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32 value = 0;
    uint8 step=0;
    sys_dot1ae_chan_t* p_sys_sec_chan = NULL;
    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_DOT1AE_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_sc);

    SYS_DOT1AE_LOCK(lchip);
    p_sys_sec_chan = _sys_usw_dot1ae_chan_lookup(lchip,  p_sc->chan_id);
    if(!p_sys_sec_chan)
    {
        SYS_DOT1AE_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }
    if (DRV_FROM_AT(lchip) && (!p_sys_sec_chan->binded))
    {
        SYS_DOT1AE_UNLOCK(lchip);
        return CTC_E_NONE;
    }

    p_sc->dir = p_sys_sec_chan->dir;
    switch (p_sc->property)
    {
        case CTC_DOT1AE_SC_PROP_AN_EN:
            if ((DRV_FROM_TMM(lchip)) || p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_RX)
            {
                p_sc->data = p_sys_sec_chan->an_en;
            }
            else
            {
                step = EpeDot1AeAnCtl0_array_1_currentAn_f - EpeDot1AeAnCtl0_array_0_currentAn_f;
                cmd = DRV_IOR(EpeDot1AeAnCtl0_t, EpeDot1AeAnCtl0_array_0_currentAn_f + step*(p_sys_sec_chan->sc_index[0] << 2));
                CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &value), ret, error_proc);
                CTC_BIT_SET(p_sc->data, value);  /*in use*/
            }
            break;
        case CTC_DOT1AE_SC_PROP_INCLUDE_SCI:
            p_sc->data = p_sys_sec_chan->include_sci ;
            break;
        case CTC_DOT1AE_SC_PROP_SCI:
            if(!p_sc->ext_data)
            {
                SYS_DOT1AE_UNLOCK(lchip);
                return CTC_E_INVALID_PARAM;
            }
            if (p_sys_sec_chan->sci)
            {
                sal_memcpy((uint8*)p_sc->ext_data, p_sys_sec_chan->sci, SYS_DOT1AE_SCI_LEN);
            }
            break;
        case CTC_DOT1AE_SC_PROP_REPLAY_WINDOW_SIZE:
            if (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX)
            {
                SYS_DOT1AE_UNLOCK(lchip);
                return CTC_E_NOT_SUPPORT;
            }
            p_sc->data = p_sys_sec_chan->replayProtectWindow;
            break;
        case CTC_DOT1AE_SC_PROP_REPLAY_PROTECT_EN:
            if(p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX)
            {
                SYS_DOT1AE_UNLOCK(lchip);
                return CTC_E_NOT_SUPPORT;
            }
            p_sc->data = p_sys_sec_chan->replayProtect;
            break;
        case CTC_DOT1AE_SC_PROP_SA_CFG:
            if(!p_sc->ext_data)
            {
                SYS_DOT1AE_UNLOCK(lchip);
                return CTC_E_INVALID_PARAM;
            }
            ret = _sys_usw_dot1ae_get_sa_cfg(lchip,p_sys_sec_chan,p_sc->ext_data);
            break;
    	case CTC_DOT1AE_SC_PROP_PROTOCOL_MODE :
    		p_sc->data = p_sys_sec_chan->protocol_type ;
            break;
        default :
            break;
    }

    error_proc:
    SYS_DOT1AE_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_dot1ae_set_global_cfg(uint8 lchip, ctc_dot1ae_glb_cfg_t* p_glb_cfg)
{
    SYS_DOT1AE_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_glb_cfg);

    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n",__FUNCTION__);
    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Dot1AE Encrypt-pn-thrd: %"PRIu64", Decrypt-pn-thrd: %"PRIu64", port_mirror_pkt_type: %u\n",\
                          p_glb_cfg->tx_pn_thrd, p_glb_cfg->rx_pn_thrd,p_glb_cfg->dot1ae_port_mirror_mode);

    if(DRV_IS_DUET2(lchip) || (DRV_FROM_TM(lchip) && (!p_glb_cfg->is_xpn)))
    {
        CTC_MAX_VALUE_CHECK(p_glb_cfg->is_xpn, 0);
        CTC_MAX_VALUE_CHECK(p_glb_cfg->tx_pn_thrd, 0xffffffff);
        CTC_MAX_VALUE_CHECK(p_glb_cfg->rx_pn_thrd, 0xffffffff);
    }
    CTC_MAX_VALUE_CHECK(p_glb_cfg->algorithm_type, CTC_DOT1AE_ALG_TYPE_SM4);
    CTC_MAX_VALUE_CHECK(p_glb_cfg->ctc_sh_mode, 1);
    CTC_MAX_VALUE_CHECK(p_glb_cfg->dot1ae_port_mirror_mode, DRV_FROM_TMM(lchip)?0:1);
    CTC_MAX_VALUE_CHECK(p_glb_cfg->key_type.packet_type, CTC_DOT1AE_PKT_MAX-1);
    CTC_MAX_VALUE_CHECK(p_glb_cfg->key_type.key_type, CTC_DOT1AE_KEY_MAX-1);
    CTC_MAX_VALUE_CHECK(p_glb_cfg->key_type.dir, CTC_EGRESS);
    usw_dot1ae_master[lchip]->is_xpn = p_glb_cfg->is_xpn;
    if (MCHIP_1AE(lchip)->set_glb_cfg)
    {
        CTC_ERROR_RETURN(MCHIP_1AE(lchip)->set_glb_cfg(lchip, p_glb_cfg));
    }

    return CTC_E_NONE;
}

int32
sys_usw_dot1ae_get_global_cfg(uint8 lchip, ctc_dot1ae_glb_cfg_t* p_glb_cfg)
{
    SYS_DOT1AE_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_glb_cfg);

    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n",__FUNCTION__);
    p_glb_cfg->is_xpn = usw_dot1ae_master[lchip]->is_xpn;

    if (MCHIP_1AE(lchip)->get_glb_cfg)
    {
        CTC_ERROR_RETURN(MCHIP_1AE(lchip)->get_glb_cfg(lchip, p_glb_cfg));
    }

    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Dot1AE Encrypt-pn-thrd: %"PRIu64", Decrypt-pn-thrd: %"PRIu64",port_mirror_pkt_type: %u\n",\
                          p_glb_cfg->tx_pn_thrd, p_glb_cfg->rx_pn_thrd, p_glb_cfg->dot1ae_port_mirror_mode);

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dot1ae_show_status_traverse(sys_dot1ae_chan_t* p_sys_chan,void* user_data)
{
    uint8  an_en = 0;
    char value2str[20] = {0};
    uint8 lchip = 0;
    uint8 dp_bmp =0;
    ctc_slistnode_t        *node = NULL;

    sys_dot1ae_chan_bind_node_t* p_sec_chan_bind_node = NULL;
    sys_traverse_t* traversal_data = (sys_traverse_t *)user_data;
    uint32* rx_chan_count = NULL;
    uint32* tx_chan_count = NULL;
    tx_chan_count = (uint32*)traversal_data->data;
    rx_chan_count = (uint32*)traversal_data->data1;
    lchip = traversal_data->value2;
    if ((!p_sys_chan->valid) || (traversal_data->value1 != p_sys_chan->binding_type))
    {
        return CTC_E_NONE;
    }
    node = p_sys_chan->bind_mem_list->head;
    p_sec_chan_bind_node = _ctc_container_of(node, sys_dot1ae_chan_bind_node_t, head);
    an_en = p_sys_chan->an_en;
    if (p_sys_chan->dir == CTC_DOT1AE_SC_DIR_TX )
    {
        (*tx_chan_count)++;
    }
    else
    {
        (*rx_chan_count)++;
    }
    dp_bmp = (CTC_SLISTCOUNT(p_sys_chan->bind_mem_list) || p_sys_chan->binded)?p_sys_chan->dp_bmp:((1<<MCHIP_CAP(SYS_CAP_DP_MAX_NUM))-1);
    SYS_DOT1AE_FOREACH_DP_BEGIN(dp_bmp)
    if (DRV_FROM_AT(lchip))
    {
        sal_sprintf(value2str,"%u",p_sys_chan->gport);
        if (CTC_SLISTCOUNT(p_sys_chan->bind_mem_list))
        {
            SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-15s%-10u%-6s%-9u%-15s%-9u%-11u%-8u\n", \
            "macsec p2p",p_sys_chan->chan_id, p_sys_chan->dir? "rx" : "tx", p_sys_chan->sc_index[dp_idx], value2str, p_sys_chan->an_valid, an_en,dp_idx);
        }
        else if (p_sys_chan->is_use_plain)
        {
            SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-15s%-10u%-6s%-9u%-15s%-9u%-11u%-8u\n", \
            "plain strategy",p_sys_chan->chan_id, p_sys_chan->dir? "rx" : "tx", 0, "entry exist", 0, 0,dp_idx);
        }
        else if (SYS_DOT1AE_BIND_TYPE_ENTRY == p_sys_chan->binding_type && p_sys_chan->binded)
        {
            SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-15s%-10u%-6s%-9u%-15s%-9u%-11u%-8u\n", \
            "cloudsec",p_sys_chan->chan_id, p_sys_chan->dir? "rx" : "tx", p_sys_chan->sc_index[dp_idx], "entry exist", p_sys_chan->an_valid, an_en,dp_idx);
        }
        else if (p_sys_chan->p2mp)
        {
            SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-15s%-10u%-6s%-9u%-15s%-9u%-11u%-8u\n", \
            "macsec p2mp",p_sys_chan->chan_id, p_sys_chan->dir? "rx" : "tx", p_sys_chan->sc_index[dp_idx], p_sys_chan->binded?value2str:"no binding", p_sys_chan->an_valid, an_en,dp_idx);
        }
        else
        {
            SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-15s%-10u%-6s%-9u%-15s%-9u%-11u%-8u\n", \
            "none",p_sys_chan->chan_id, p_sys_chan->dir? "rx" : "tx", p_sys_chan->sc_index[dp_idx], "no binding", p_sys_chan->an_valid, an_en,dp_idx);
        }
    }
    else
    {
        if (CTC_SLISTCOUNT(p_sys_chan->bind_mem_list))
        {
            CTC_SLIST_LOOP(p_sys_chan->bind_mem_list, node)
            {
                p_sec_chan_bind_node = _ctc_container_of(node, sys_dot1ae_chan_bind_node_t, head);
                sal_sprintf(value2str,"%u",p_sec_chan_bind_node->value);
                SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-15s%-10u%-6s%-9u%-15s%-9u%-11u%-8u\n", \
                ((SYS_DOT1AE_BIND_TYPE_PORT == p_sys_chan->binding_type)?"macsec":"cloudsec"),p_sys_chan->chan_id, p_sys_chan->dir? "rx" : "tx", p_sys_chan->sc_index[dp_idx], \
                value2str, p_sys_chan->an_valid, an_en,dp_idx);
            }
        }
        else
        {
            SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-15s%-10u%-6s%-9u%-15s%-9u%-11u%-8u\n", \
            "unbinding chan",p_sys_chan->chan_id, p_sys_chan->dir? "rx" : "tx", p_sys_chan->sc_index[dp_idx], "no binding", p_sys_chan->an_valid, an_en,dp_idx);
        }
    }
    SYS_DOT1AE_FOREACH_DP_END

    return CTC_E_NONE;
}


int32
sys_usw_dot1ae_show_status(uint8 lchip)
{
    uint32 rx_chan_count = 0, tx_chan_count = 0;
    sys_traverse_t user_data;
    uint32 chan_count = 0;
    char *binding_type_str[SYS_DOT1AE_BIND_TYPE_MAX] = {"port", "nh-id", "logic-port","entry"};
    SYS_DOT1AE_INIT_CHECK(lchip);
    sal_memset(&user_data, 0 , sizeof(sys_traverse_t));
    user_data.data = (void*)&tx_chan_count;
    user_data.data1 = (void*)&rx_chan_count;
    user_data.value2 = lchip;
    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------Dot1AE Overall Status -----------------------------------\n");

    for (user_data.value1 = SYS_DOT1AE_BIND_TYPE_PORT;user_data.value1 < SYS_DOT1AE_BIND_TYPE_MAX;user_data.value1++)
    {
        SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-15s%-10s%-6s%-9s%-15s%-9s%-11s%-8s\n","type","chan_id","Dir",\
        "sc-idx",binding_type_str[user_data.value1],"AN-CFG","AN-InUse","DP-ID");
        CTC_ERROR_RETURN(ctc_hash_traverse(usw_dot1ae_master[lchip]->chan_hash, (hash_traversal_fn)_sys_usw_dot1ae_show_status_traverse, (void *)&user_data));
        SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "----------------------------------------------------------------------------------\n");
    }

    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "Channel Resource:\n");
    chan_count = (tx_chan_count + rx_chan_count) ;
    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%u \n", "Used Channel count", chan_count);
    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%u \n", "Tx channel number", tx_chan_count);
    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%u \n", "Rx channel number", rx_chan_count);
    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "----------------------------------------------------------------------------------\n");
    return CTC_E_NONE;

}

STATIC int32
_sys_usw_dot1ae_chan_sync_traverse(sys_dot1ae_chan_t* p_sys_chan, void* user_data)
{
    ctc_wb_data_t*  wb_data = NULL;
    uint32 max_entry_cnt = 0;
    sys_wb_dot1ae_channel_t  *p_wb_dot1ae_channel = NULL;
    sys_traverse_t* traversal_data = (sys_traverse_t *)user_data;
    wb_data = (ctc_wb_data_t*)traversal_data->data;
    max_entry_cnt = wb_data->buffer_len / (wb_data->key_len + wb_data->data_len);
    p_wb_dot1ae_channel = (sys_wb_dot1ae_channel_t *)wb_data->buffer + wb_data->valid_cnt;
    sal_memset(p_wb_dot1ae_channel, 0, sizeof(sys_wb_dot1ae_channel_t));
    if  (p_sys_chan->valid && (p_sys_chan->binded || CTC_SLISTCOUNT(p_sys_chan->bind_mem_list)))
    {
        p_wb_dot1ae_channel->chan_id = p_sys_chan->chan_id;
        p_wb_dot1ae_channel->dir = p_sys_chan->dir;
        p_wb_dot1ae_channel->sc_index[0] = p_sys_chan->sc_index[0];
        p_wb_dot1ae_channel->sc_index[1] = p_sys_chan->sc_index[1];
        p_wb_dot1ae_channel->pp_id = p_sys_chan->pp_id;
        p_wb_dot1ae_channel->include_sci = p_sys_chan->include_sci;
        p_wb_dot1ae_channel->an_en = p_sys_chan->an_en;
        p_wb_dot1ae_channel->an_valid = p_sys_chan->an_valid;
        p_wb_dot1ae_channel->binding_type = p_sys_chan->binding_type;
        p_wb_dot1ae_channel->pn_mode = p_sys_chan->pn_mode;
        p_wb_dot1ae_channel->is_xpn = p_sys_chan->is_xpn;
        p_wb_dot1ae_channel->macsecType = p_sys_chan->macsecType;

        p_wb_dot1ae_channel->p2mp = p_sys_chan->p2mp;
        p_wb_dot1ae_channel->clear_tag_en= p_sys_chan->clear_tag_en;
        p_wb_dot1ae_channel->binded= p_sys_chan->binded;
        p_wb_dot1ae_channel->an[0] = p_sys_chan->sa_cfg[0].an;
        p_wb_dot1ae_channel->an[1] = p_sys_chan->sa_cfg[1].an;
        p_wb_dot1ae_channel->scl_id = p_sys_chan->scl_id;
        p_wb_dot1ae_channel->is_use_plain = p_sys_chan->is_use_plain;
        p_wb_dot1ae_channel->ref_cnt[0] = p_sys_chan->ref_cnt[0];
        p_wb_dot1ae_channel->ref_cnt[1] = p_sys_chan->ref_cnt[1];
        p_wb_dot1ae_channel->gport= p_sys_chan->gport;
        p_wb_dot1ae_channel->dp_bmp= p_sys_chan->dp_bmp;
        if (++wb_data->valid_cnt == max_entry_cnt)
        {
            CTC_ERROR_RETURN(ctc_wb_add_entry(wb_data));
            wb_data->valid_cnt = 0;
        }
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dot1ae_entry_sync_traverse(sys_dot1ae_entry_t* p_sys_entry, void* user_data)
{
    ctc_wb_data_t*  wb_data = NULL;
    uint32 max_entry_cnt = 0;
    sys_wb_dot1ae_entry_t  *p_wb_dot1ae_entry = NULL;
    sys_traverse_t* traversal_data = (sys_traverse_t *)user_data;
    wb_data = (ctc_wb_data_t*)traversal_data->data;
    max_entry_cnt = wb_data->buffer_len / (wb_data->key_len + wb_data->data_len);
    p_wb_dot1ae_entry = (sys_wb_dot1ae_entry_t *)wb_data->buffer + wb_data->valid_cnt;
    sal_memset(p_wb_dot1ae_entry, 0, sizeof(sys_wb_dot1ae_entry_t));

    p_wb_dot1ae_entry->entry_id = p_sys_entry->entry_id;
    p_wb_dot1ae_entry->chan_id = p_sys_entry->chan_id;
    p_wb_dot1ae_entry->dir = p_sys_entry->dir;
    p_wb_dot1ae_entry->key_type = p_sys_entry->key_type;
    p_wb_dot1ae_entry->dp_bmp = p_sys_entry->dp_bmp;
    p_wb_dot1ae_entry->is_cam = (p_sys_entry->is_cam[1]<<1 | p_sys_entry->is_cam[0])&0x3;
    p_wb_dot1ae_entry->hash_key_index[0] = p_sys_entry->hash_key_index[0];
    p_wb_dot1ae_entry->hash_key_index[1] = p_sys_entry->hash_key_index[1];
    p_wb_dot1ae_entry->gport = p_sys_entry->gport;
    if (++wb_data->valid_cnt == max_entry_cnt)
    {
        CTC_ERROR_RETURN(ctc_wb_add_entry(wb_data));
        wb_data->valid_cnt = 0;
    }
    return CTC_E_NONE;
}



STATIC int32
_sys_usw_dot1ae_node_sync_traverse(sys_dot1ae_chan_t* p_sys_chan, void* user_data)
{
    ctc_wb_data_t*  wb_data = NULL;
    uint32 max_entry_cnt = 0;
    sys_dot1ae_chan_bind_node_t* p_sec_chan_bind_node = NULL;
    sys_wb_dot1ae_channel_bind_node_t  *p_wb_dot1ae_chan_bind_node = NULL;
    ctc_slistnode_t        *node = NULL;
    sys_traverse_t* traversal_data = (sys_traverse_t *)user_data;
    wb_data = (ctc_wb_data_t*)traversal_data->data;
    max_entry_cnt = wb_data->buffer_len / (wb_data->key_len + wb_data->data_len);
    if (p_sys_chan->valid)
    {
        CTC_SLIST_LOOP(p_sys_chan->bind_mem_list, node)
        {
            p_sec_chan_bind_node = _ctc_container_of(node, sys_dot1ae_chan_bind_node_t, head);
            p_wb_dot1ae_chan_bind_node = (sys_wb_dot1ae_channel_bind_node_t *)wb_data->buffer + wb_data->valid_cnt;
            p_wb_dot1ae_chan_bind_node->value = p_sec_chan_bind_node->value;
            p_wb_dot1ae_chan_bind_node->dir = p_sys_chan->dir;
            p_wb_dot1ae_chan_bind_node->chan_id= p_sys_chan->chan_id;
            if (++wb_data->valid_cnt == max_entry_cnt)
            {
                CTC_ERROR_RETURN(ctc_wb_add_entry(wb_data));
                wb_data->valid_cnt = 0;
            }
        }
    }
    return CTC_E_NONE;
}


int32
sys_usw_dot1ae_wb_sync(uint8 lchip,uint32 app_id)
{

    int32 ret = CTC_E_NONE;
    ctc_wb_data_t wb_data;
    sys_wb_dot1ae_master_t*p_wb_dot1ae_master = NULL;
    sys_traverse_t user_data;

    sal_memset(&wb_data, 0, sizeof(ctc_wb_data_t));
    sal_memset(&user_data, 0, sizeof(sys_traverse_t));
    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /*syncup  dot1ae_matser*/
    CTC_WB_ALLOC_BUFFER(&wb_data.buffer);
    SYS_DOT1AE_LOCK(lchip);
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_DOT1AE_SUBID_MASTER)
    {
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_dot1ae_master_t, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_MASTER);

        p_wb_dot1ae_master = (sys_wb_dot1ae_master_t  *)wb_data.buffer;
        p_wb_dot1ae_master->lchip = lchip;
        p_wb_dot1ae_master->version = SYS_WB_VERSION_DOT1AE;
        /*
        p_wb_dot1ae_master->in_pkts_no_sci = usw_dot1ae_master[lchip]->global_stats.in_pkts_no_sci;
        p_wb_dot1ae_master->in_pkts_unknown_sci = usw_dot1ae_master[lchip]->global_stats.in_pkts_unknown_sci;
        */
        sal_memcpy(p_wb_dot1ae_master->dp0_rx_bmp, usw_dot1ae_master[lchip]->dp0_rx_bmp, sizeof(p_wb_dot1ae_master->dp0_rx_bmp));
        sal_memcpy(p_wb_dot1ae_master->dp0_tx_bmp, usw_dot1ae_master[lchip]->dp0_tx_bmp, sizeof(p_wb_dot1ae_master->dp0_tx_bmp));
        sal_memcpy(p_wb_dot1ae_master->dp1_rx_bmp, usw_dot1ae_master[lchip]->dp1_rx_bmp, sizeof(p_wb_dot1ae_master->dp1_rx_bmp));
        sal_memcpy(p_wb_dot1ae_master->dp1_tx_bmp, usw_dot1ae_master[lchip]->dp1_tx_bmp, sizeof(p_wb_dot1ae_master->dp1_tx_bmp));
        wb_data.valid_cnt = 1;
        CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_MASTER);
    }

    sal_memset(&user_data, 0 , sizeof(sys_traverse_t));
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_DOT1AE_SUBID_CHANNEL)
    {
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_dot1ae_channel_t, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_CHANNEL);
        user_data.data = (void*)&wb_data;
        CTC_ERROR_GOTO(ctc_hash_traverse(usw_dot1ae_master[lchip]->chan_hash, (hash_traversal_fn)_sys_usw_dot1ae_chan_sync_traverse, (void *)&user_data), ret, done);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_CHANNEL);
    }
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_DOT1AE_SUBID_CHAN_BIND_NODE)
    {
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_dot1ae_channel_bind_node_t, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_CHAN_BIND_NODE);
        sal_memset(&user_data, 0 , sizeof(sys_traverse_t));
        user_data.data = (void*)&wb_data;
        CTC_ERROR_GOTO(ctc_hash_traverse(usw_dot1ae_master[lchip]->chan_hash, (hash_traversal_fn)_sys_usw_dot1ae_node_sync_traverse, (void *)&user_data), ret, done);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_CHAN_BIND_NODE);
    }
    if ((DRV_FROM_AT(lchip)) && (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_DOT1AE_SUBID_ENTRY))
    {
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_dot1ae_entry_t, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_ENTRY);
        sal_memset(&user_data, 0 , sizeof(sys_traverse_t));
        user_data.data = (void*)&wb_data;
        CTC_ERROR_GOTO(ctc_hash_traverse(usw_dot1ae_master[lchip]->entry_hash, (hash_traversal_fn)_sys_usw_dot1ae_entry_sync_traverse, (void *)&user_data), ret, done);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_ENTRY);
    }
    done:
    SYS_DOT1AE_UNLOCK(lchip);
    CTC_WB_FREE_BUFFER(wb_data.buffer);
    return ret;

}
int32
_sys_usw_dot1ae_wb_init(uint8 lchip)
{
   ctc_wb_appid_t  appid;
   sal_memset(&appid,0,sizeof(appid));

   appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_MASTER) ;
   appid.entry_num = 1;
   appid.entry_size  = sizeof(sys_wb_dot1ae_master_t);
   ctc_wb_add_appid( lchip, &appid);

   appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_CHANNEL) ;
   appid.entry_num = MCHIP_CAP(SYS_CAP_DOT1AE_SEC_CHAN_NUM)*2;
   appid.entry_size  = sizeof(sys_wb_dot1ae_channel_t);
   ctc_wb_add_appid( lchip, &appid);

   appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_CHAN_BIND_NODE) ;
   appid.entry_num = DRV_FROM_AT(lchip) ? MCHIP_CAP(SYS_CAP_SPEC_MAX_PHY_PORT_NUM)
                        : (MCHIP_CAP(SYS_CAP_SPEC_MAX_PHY_PORT_NUM) + SYS_FTM_SPEC(lchip,CTC_FTM_SPEC_TUNNEL)*2);
   appid.entry_size  = sizeof(sys_wb_dot1ae_channel_bind_node_t);
   ctc_wb_add_appid( lchip, &appid);

   appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_ENTRY) ;
   appid.entry_num = MCHIP_CAP(SYS_CAP_DOT1AE_ENTR_NUM) ;
   appid.entry_size  = sizeof(sys_wb_dot1ae_entry_t);
   ctc_wb_add_appid( lchip, &appid);
   return 0;
}


int32 _sys_usw_dot1ae_restore_chan_cfg_traverse(sys_dot1ae_chan_t* p_sys_chan, void* user_data)
{
    sys_traverse_t* traversal_data = (sys_traverse_t *)user_data;
    uint8 lchip = traversal_data->value1;
    return MCHIP_1AE(lchip)->wb_chan_restore(lchip, p_sys_chan);
}


int32 _sys_usw_dot1ae_restore_unbind_chan_traverse(sys_dot1ae_chan_t* p_sys_chan, void* user_data)
{
    sys_traverse_t* traversal_data = (sys_traverse_t *)user_data;
    sys_dot1ae_chan_t* chan_insert = NULL;
    uint8 lchip = traversal_data->value1;
    uint8 tmp_lchip = 0;
    if (!(p_sys_chan->binded | CTC_SLISTCOUNT(p_sys_chan->bind_mem_list)))
    {
        return CTC_E_NONE;
    }
    for (tmp_lchip = SYS_PP_BASE(lchip); tmp_lchip < SYS_PP_NUM(lchip); tmp_lchip++)
    {
        if (tmp_lchip != lchip && !_sys_usw_dot1ae_chan_lookup(tmp_lchip, p_sys_chan->chan_id))
        {
            chan_insert = mem_malloc(MEM_DOT1AE_MODULE, sizeof(sys_dot1ae_chan_t));
            if (chan_insert == NULL)
            {
                return CTC_E_NO_MEMORY;
            }
            sal_memcpy(chan_insert, p_sys_chan, sizeof(sys_dot1ae_chan_t));
            chan_insert->binded = 0;
            chan_insert->binding_type = 0;
            chan_insert->bind_mem_list = ctc_slist_new();
            chan_insert->pp_id = 0;
            chan_insert->dp_id = 0;
            chan_insert->dp_bmp = 0;
            chan_insert->sc_index[0] = 0;
            chan_insert->sc_index[1] = 0;
            chan_insert->is_use_plain = 0;
            chan_insert->gport = 0;
            chan_insert->sci = mem_malloc(MEM_DOT1AE_MODULE, SYS_DOT1AE_SCI_LEN);
            sal_memcpy(chan_insert->sci, p_sys_chan->sci, SYS_DOT1AE_SCI_LEN);
            chan_insert->sa_cfg = mem_malloc(MEM_DOT1AE_MODULE, sizeof(sys_dot1ae_sa_config_t) * MCHIP_CAP(SYS_CAP_DOT1AE_SA_PER_CHAN));
            sal_memcpy(chan_insert->sa_cfg, p_sys_chan->sa_cfg, sizeof(sys_dot1ae_sa_config_t) * MCHIP_CAP(SYS_CAP_DOT1AE_SA_PER_CHAN));
            chan_insert->an_stats = mem_malloc(MEM_DOT1AE_MODULE, sizeof(sys_at_dot1ae_an_stats_t) * MCHIP_CAP(SYS_CAP_DOT1AE_STATS_PER_CHAN));

            if ((!chan_insert->sa_cfg) || (!chan_insert->an_stats))
            {
               mem_free(chan_insert->sa_cfg);
               mem_free(chan_insert->an_stats);
               mem_free(chan_insert);
               return CTC_E_NO_MEMORY;
            }
            _sys_usw_dot1ae_chan_add_db(tmp_lchip, chan_insert);
            
        }
    }
    return CTC_E_NONE;
}



STATIC int32 sys_usw_dot1ae_restore_unbind_chan(uint8 lchip)
{
    sys_traverse_t user_data;
    uint8 tmp_lchip = 0;
    sal_memset(&user_data, 0 , sizeof(sys_traverse_t));
    user_data.value1 = lchip;
    for (tmp_lchip = SYS_PP_BASE(lchip); tmp_lchip < lchip + 1; tmp_lchip++)
    {
        user_data.value1 = tmp_lchip;
        ctc_hash_traverse(usw_dot1ae_master[tmp_lchip]->chan_hash,
                           (hash_traversal_fn)_sys_usw_dot1ae_restore_unbind_chan_traverse, (void *)&user_data);
    }
    return CTC_E_NONE;
}

int32
sys_usw_dot1ae_wb_restore(uint8 lchip)
{
    ctc_wb_query_t wb_query;
    uint32 entry_cnt = 0;
    int32 ret =0;
    sys_usw_opf_t opf;
    sys_wb_dot1ae_master_t*  p_wb_dot1ae_master=NULL;
    sys_wb_dot1ae_channel_t   wb_dot1ae_channel;
    sys_wb_dot1ae_entry_t   wb_dot1ae_entry;
    sys_dot1ae_chan_t* p_sys_chan = NULL;
    sys_dot1ae_entry_t* p_sys_entry = NULL;
    sys_dot1ae_chan_bind_node_t* p_sec_chan_bind_node = NULL;
    sys_dot1ae_maskbmp_t maskbmp;
    sys_dot1ae_maskbmp_t* out_mask_bmp;
    ctc_spool_t* spool = NULL;
    sys_wb_dot1ae_channel_bind_node_t wb_dot1ae_chan_bind_node;
    sys_traverse_t user_data;
    uint32 cmd = 0;
    uint8 size_an_stats=0;

    SYS_DOT1AE_INIT_CHECK(lchip);

    sal_memset(&wb_query, 0, sizeof(ctc_wb_query_t));
    sal_memset(&wb_dot1ae_channel, 0, sizeof(sys_wb_dot1ae_channel_t));
    sal_memset(&wb_dot1ae_chan_bind_node, 0, sizeof(sys_wb_dot1ae_channel_bind_node_t));
    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));

    CTC_WB_ALLOC_BUFFER(&wb_query.buffer);

    p_wb_dot1ae_master = (sys_wb_dot1ae_master_t*)mem_malloc(MEM_DOT1AE_MODULE, sizeof(sys_wb_dot1ae_master_t));
    if (NULL == p_wb_dot1ae_master)
    {
        ret = CTC_E_NO_MEMORY;
        goto done;
    }
    /*restore  dot1ae_master*/
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_dot1ae_master_t, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_MASTER);
    sal_memset(p_wb_dot1ae_master, 0, sizeof(sys_wb_dot1ae_master_t));

    CTC_ERROR_GOTO(ctc_wb_query_entry(&wb_query), ret, done);


    sal_memcpy(p_wb_dot1ae_master, wb_query.buffer,  wb_query.key_len + wb_query.data_len);
    sal_memcpy(usw_dot1ae_master[lchip]->dp0_rx_bmp, p_wb_dot1ae_master->dp0_rx_bmp, sizeof(p_wb_dot1ae_master->dp0_rx_bmp));
    sal_memcpy(usw_dot1ae_master[lchip]->dp0_tx_bmp, p_wb_dot1ae_master->dp0_tx_bmp, sizeof(p_wb_dot1ae_master->dp0_tx_bmp));
    sal_memcpy(usw_dot1ae_master[lchip]->dp1_rx_bmp, p_wb_dot1ae_master->dp1_rx_bmp, sizeof(p_wb_dot1ae_master->dp1_rx_bmp));
    sal_memcpy(usw_dot1ae_master[lchip]->dp1_tx_bmp, p_wb_dot1ae_master->dp1_tx_bmp, sizeof(p_wb_dot1ae_master->dp1_tx_bmp));

    if (CTC_WB_VERSION_CHECK(SYS_WB_VERSION_DOT1AE, p_wb_dot1ae_master->version))
    {
        ret = CTC_E_VERSION_MISMATCH;
        goto done;
    }

    if (DRV_FROM_AT(lchip))
    {
        uint32 tbl_id = 0;
        uint16 lport = 0;
        uint8 gchip = 0;
        uint32 sub_idx = 0;
        uint8 dir = 0;
        uint8 index = 0;
        uint8 max_profile = 0;
        uint8 min_profile = 0;
        uint32 dp_id = 0;
        uint32 pro_id =0;
        /*In egress direction,the packet types vxlan/gre/udp of ipv4 or ipv6 have the same mask profile id,
        so only need restore bits 0,3,4,9,10 for spool*/
        uint32 tmp_bmp = 0x19E6 << XSecTxLookupChanCtl_array_0_maskProfileId_f;
        sys_usw_dmps_port_info_t dmps_port_info = {0};
        for (lport = 0; lport < MCHIP_CAP(SYS_CAP_PORT_NUM_PER_CHIP); lport++)
        {
            uint32 port_type = 0;
            uint32 pp_id = 0;
            CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip));
            dmps_port_info.gport = CTC_MAP_LPORT_TO_GPORT(gchip, lport);
            sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE, &port_type);
            sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PP_ID, &pp_id);
            sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_SUB_CHAN_ID, &sub_idx);
            sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_DP_ID, &dp_id);
            if (SYS_DMPS_NETWORK_PORT != port_type || pp_id != (lchip % sys_usw_vchip_get_pp_num(lchip)))
            {
                continue;
            }
            for (dir = 0; dir < CTC_BOTH_DIRECTION; dir++)
            {
                spool = (CTC_INGRESS == dir) ? (dp_id ? usw_dot1ae_master[lchip]->dp1_rx_spool : usw_dot1ae_master[lchip]->dp0_rx_spool):\
                                               (dp_id ? usw_dot1ae_master[lchip]->dp1_tx_spool : usw_dot1ae_master[lchip]->dp0_tx_spool);
                max_profile = ((CTC_INGRESS == dir)? XSecRxLookupChanCtl_array_14_maskProfileId_f : XSecTxLookupChanCtl_array_12_maskProfileId_f) + 1;
                min_profile = ((CTC_INGRESS == dir)? XSecRxLookupChanCtl_array_0_maskProfileId_f : XSecTxLookupChanCtl_array_0_maskProfileId_f);
                sal_memset(&maskbmp, 0, sizeof(sys_dot1ae_maskbmp_t));
                for (index = min_profile; index < max_profile; index++)
                {
                    tbl_id = (CTC_INGRESS == dir) ? XSecRxLookupChanCtl_t : XSecTxLookupChanCtl_t;
                    cmd = DRV_IOR(tbl_id, index);
                    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, sub_idx, DRV_CMD_DP_EN(cmd, dp_id), &pro_id));
                    if (0 == pro_id || (dir && CTC_IS_BIT_SET(tmp_bmp, index)))
                    {
                        continue;
                    }
                    tbl_id = (CTC_INGRESS == dir) ? XSecRxLookupDpCtl_t : XSecTxLookupDpCtl_t;
                    maskbmp.index.index = pro_id;
                    cmd = DRV_IOR(tbl_id, pro_id);
                    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), &maskbmp.mask_bitmap));
                    CTC_ERROR_RETURN(ctc_spool_add(spool, &maskbmp, NULL, &out_mask_bmp));
                }

            }
        }
    }

    /*restore  dot1ae channel entry*/
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_dot1ae_channel_t, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_CHANNEL);
    sal_memset(&wb_dot1ae_channel, 0, sizeof(sys_wb_dot1ae_channel_t));
    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
    sal_memcpy(&wb_dot1ae_channel, (sys_wb_dot1ae_channel_t *)wb_query.buffer + entry_cnt,  wb_query.key_len + wb_query.data_len);
    entry_cnt++;
    if (NULL == _sys_usw_dot1ae_chan_lookup(lchip, wb_dot1ae_channel.chan_id))
    {
        p_sys_chan = mem_malloc(MEM_DOT1AE_MODULE, sizeof(sys_dot1ae_chan_t));
        if (NULL == p_sys_chan)
        {
            return CTC_E_NO_MEMORY;
        }
        sal_memset(p_sys_chan, 0, sizeof(sys_dot1ae_chan_t));
        p_sys_chan->sa_cfg = mem_malloc(MEM_DOT1AE_MODULE, sizeof(sys_dot1ae_sa_config_t) * MCHIP_CAP(SYS_CAP_DOT1AE_SA_PER_CHAN));
        size_an_stats = DRV_FROM_AT(lchip)? sizeof(sys_at_dot1ae_an_stats_t) : ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip))? sizeof(sys_tmm_dot1ae_an_stats_t) : sizeof(sys_tm_dot1ae_an_stats_t));
        p_sys_chan->an_stats = mem_malloc(MEM_DOT1AE_MODULE, size_an_stats * MCHIP_CAP(SYS_CAP_DOT1AE_STATS_PER_CHAN));

        if ((!p_sys_chan->sa_cfg) || (!p_sys_chan->an_stats))
        {
            goto error1;
        }
        sal_memset(p_sys_chan->an_stats, 0 , size_an_stats * MCHIP_CAP(SYS_CAP_DOT1AE_STATS_PER_CHAN));
        sal_memset(p_sys_chan->sa_cfg, 0 , sizeof(sys_dot1ae_sa_config_t) * MCHIP_CAP(SYS_CAP_DOT1AE_SA_PER_CHAN));
        p_sys_chan->chan_id = wb_dot1ae_channel.chan_id;
        p_sys_chan->dir = wb_dot1ae_channel.dir;
        p_sys_chan->sc_index[0] = wb_dot1ae_channel.sc_index[0];
        p_sys_chan->sc_index[1] = wb_dot1ae_channel.sc_index[1];
        p_sys_chan->valid = 1;
        p_sys_chan->include_sci = wb_dot1ae_channel.include_sci;
        p_sys_chan->an_en = wb_dot1ae_channel.an_en;
        p_sys_chan->an_valid = wb_dot1ae_channel.an_valid;
        p_sys_chan->macsecType = wb_dot1ae_channel.macsecType;
        p_sys_chan->binding_type = wb_dot1ae_channel.binding_type;
        p_sys_chan->bind_mem_list = ctc_slist_new();
        p_sys_chan->pn_mode= wb_dot1ae_channel.pn_mode;
        p_sys_chan->is_xpn= wb_dot1ae_channel.is_xpn;
        p_sys_chan->p2mp = wb_dot1ae_channel.p2mp;
        p_sys_chan->enable = wb_dot1ae_channel.enable;
        p_sys_chan->clear_tag_en = wb_dot1ae_channel.clear_tag_en;
        p_sys_chan->binded = wb_dot1ae_channel.binded;
        p_sys_chan->scl_id = wb_dot1ae_channel.scl_id;
        p_sys_chan->is_use_plain = wb_dot1ae_channel.is_use_plain;
        p_sys_chan->ref_cnt[0] = wb_dot1ae_channel.ref_cnt[0];
        p_sys_chan->ref_cnt[1] = wb_dot1ae_channel.ref_cnt[1];
        p_sys_chan->dp_bmp = wb_dot1ae_channel.dp_bmp;
        p_sys_chan->gport = wb_dot1ae_channel.gport;
        p_sys_chan->sa_cfg[0].an = wb_dot1ae_channel.an[0];
        p_sys_chan->sa_cfg[1].an = wb_dot1ae_channel.an[1];

        if(!p_sys_chan->sci)
        {
            p_sys_chan->sci = mem_malloc(MEM_DOT1AE_MODULE, SYS_DOT1AE_SCI_LEN);
            if(NULL == p_sys_chan->sci)
            {
                ret = CTC_E_NO_MEMORY;
                goto error1;
            }
        }

        if (NULL == ctc_hash_insert(usw_dot1ae_master[lchip]->chan_hash, p_sys_chan))
        {
            ret = CTC_E_NO_MEMORY;
            goto error1;
        }
    }
    CTC_WB_QUERY_ENTRY_END((&wb_query));


    /*restore  dot1ae channel bind node*/
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_dot1ae_channel_bind_node_t, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_CHAN_BIND_NODE);
    sal_memset(&wb_dot1ae_chan_bind_node, 0, sizeof(sys_wb_dot1ae_channel_bind_node_t));

    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
    sal_memcpy(&wb_dot1ae_chan_bind_node, (sys_wb_dot1ae_channel_bind_node_t *)wb_query.buffer + entry_cnt,  wb_query.key_len + wb_query.data_len);
    entry_cnt++;
    p_sys_chan = _sys_usw_dot1ae_chan_lookup(lchip, wb_dot1ae_chan_bind_node.chan_id);
    if (p_sys_chan == NULL)
    {
        return CTC_E_NOT_EXIST;
    }
    p_sec_chan_bind_node = mem_malloc(MEM_DOT1AE_MODULE, sizeof(sys_dot1ae_chan_bind_node_t));
    if (NULL == p_sec_chan_bind_node)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_sec_chan_bind_node, 0, sizeof(sys_dot1ae_chan_bind_node_t));
    p_sec_chan_bind_node->value = wb_dot1ae_chan_bind_node.value;
    ctc_slist_add_head(p_sys_chan->bind_mem_list, &(p_sec_chan_bind_node->head));
    CTC_WB_QUERY_ENTRY_END((&wb_query));

    sal_memset(&user_data, 0 , sizeof(sys_traverse_t));
    user_data.value1 = lchip;
    CTC_ERROR_GOTO(ctc_hash_traverse(usw_dot1ae_master[lchip]->chan_hash, (hash_traversal_fn)_sys_usw_dot1ae_restore_chan_cfg_traverse, (void *)&user_data), ret, error1);

    /*restore  dot1ae entry*/
    if (DRV_FROM_AT(lchip))
    {
        CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_dot1ae_entry_t, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_ENTRY);
        sal_memset(&wb_dot1ae_entry, 0, sizeof(sys_wb_dot1ae_entry_t));

        CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        sal_memcpy(&wb_dot1ae_entry, (sys_wb_dot1ae_entry_t *)wb_query.buffer + entry_cnt,  wb_query.key_len + wb_query.data_len);
        entry_cnt++;
        p_sys_entry = sys_usw_dot1ae_lkup_entry(lchip, wb_dot1ae_entry.entry_id);
        if (p_sys_entry == NULL)
        {
            p_sys_entry = mem_malloc(MEM_DOT1AE_MODULE, sizeof(sys_dot1ae_entry_t));
            if (NULL == p_sys_entry)
            {
                return CTC_E_NO_MEMORY;
            }
            p_sys_chan = _sys_usw_dot1ae_chan_lookup(lchip, wb_dot1ae_entry.chan_id);
            if (p_sys_chan == NULL)
            {
                return CTC_E_NOT_EXIST;
            }
            p_sys_entry->entry_id = wb_dot1ae_entry.entry_id;
            p_sys_entry->chan_id = wb_dot1ae_entry.chan_id;
            p_sys_entry->dir = wb_dot1ae_entry.dir;
            p_sys_entry->hash_key_index[0] = wb_dot1ae_entry.hash_key_index[0];
            p_sys_entry->hash_key_index[1] = wb_dot1ae_entry.hash_key_index[1];
            p_sys_entry->sc_index[0] = p_sys_chan->sc_index[0];
            p_sys_entry->sc_index[1] = p_sys_chan->sc_index[1];
            p_sys_entry->dp_bmp = wb_dot1ae_entry.dp_bmp;
            p_sys_entry->is_cam[0] = wb_dot1ae_entry.is_cam&0x1;
            p_sys_entry->is_cam[1] = wb_dot1ae_entry.is_cam >> 1;
            p_sys_entry->key_type = wb_dot1ae_entry.key_type;
            p_sys_entry->gport = wb_dot1ae_entry.gport;
            if (NULL == ctc_hash_insert(usw_dot1ae_master[lchip]->entry_hash, p_sys_entry))
            {
                ret = CTC_E_NO_MEMORY;
                goto error2;
            }
            sys_usw_com_wb_restore_entry_hash(lchip, p_sys_entry->entry_id, MEM_DOT1AE_MODULE,
                        usw_dot1ae_master[SYS_PP_BASE(lchip)]->entry_hash_db);
        }
        CTC_WB_QUERY_ENTRY_END((&wb_query));
    }
    
    if (DRV_FROM_AT(lchip) && (lchip == SYS_PP_BASE(lchip) + SYS_PP_NUM(lchip) - 1))
    {
        sys_usw_dot1ae_restore_unbind_chan(lchip);
    }
    goto done;

    error2:
      mem_free(p_sys_entry);
        return CTC_E_NONE;
    error1:
      mem_free(p_sys_chan->sa_cfg);
      mem_free(p_sys_chan->an_stats);
      mem_free(p_sys_chan->sci);
      mem_free(p_sys_chan);

    done:
    mem_free(p_wb_dot1ae_master);
    CTC_WB_FREE_BUFFER(wb_query.buffer);
    return ret;
}

int32
sys_usw_dot1ae_get_stats(uint8 lchip, uint32 chan_id, ctc_dot1ae_stats_t* p_stats)
{
    sys_dot1ae_chan_t* p_chan = NULL;

    if (DRV_IS_DUET2(lchip))
    {
        return CTC_E_NOT_SUPPORT;
    }
    CTC_PTR_VALID_CHECK(p_stats);
    SYS_DOT1AE_INIT_CHECK(lchip);

    SYS_DOT1AE_LOCK(lchip);

    p_chan = _sys_usw_dot1ae_chan_lookup(lchip, chan_id);
    if(NULL == p_chan)
    {
        SYS_DOT1AE_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }
    if (MCHIP_1AE(lchip)->get_stats)
    {
        CTC_ERROR_RETURN_WITH_UNLOCK(MCHIP_1AE(lchip)->get_stats(lchip, chan_id, p_stats),usw_dot1ae_master[lchip]->sec_mutex);
    }

    SYS_DOT1AE_UNLOCK(lchip);
    return CTC_E_NONE;
}


int32
sys_usw_dot1ae_show_entry(uint8 lchip, sys_dot1ae_show_entry_info_t* param)
{
    int32 ret = 0;
    SYS_DOT1AE_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(param);
    SYS_DOT1AE_LOCK(lchip);

    ret = MCHIP_1AE(lchip)->show_entry?MCHIP_1AE(lchip)->show_entry(lchip, (void*)param):CTC_E_NOT_SUPPORT;

    SYS_DOT1AE_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_dot1ae_set_hash_field_sel(uint8 lchip, ctc_dot1ae_hash_sel_t* p_hash_sel)
{
    int32 ret = 0;
    SYS_DOT1AE_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_hash_sel);
    CTC_PTR_VALID_CHECK(p_hash_sel->field_key_list);
    CTC_MIN_VALUE_CHECK(p_hash_sel->packet_type, CTC_DOT1AE_PKT_MACSEC);
    CTC_MAX_VALUE_CHECK(p_hash_sel->packet_type, CTC_DOT1AE_PKT_MAX - 1);
    CTC_MAX_VALUE_CHECK(p_hash_sel->dir, CTC_BOTH_DIRECTION - 1);
    if (CTC_EGRESS == p_hash_sel->dir && (CTC_DOT1AE_PKT_CTCSEC_IPV4 == p_hash_sel->packet_type ||\
                                          CTC_DOT1AE_PKT_CTCSEC_IPV6 == p_hash_sel->packet_type ||\
                                          CTC_DOT1AE_PKT_CLOUDSEC_IPV4 == p_hash_sel->packet_type ||\
                                          CTC_DOT1AE_PKT_CLOUDSEC_IPV6 == p_hash_sel->packet_type))
    {
        return CTC_E_INVALID_CONFIG;
    }
    SYS_DOT1AE_LOCK(lchip);

    ret = MCHIP_1AE(lchip)->set_hash_field_sel?MCHIP_1AE(lchip)->set_hash_field_sel(lchip, p_hash_sel):CTC_E_NOT_SUPPORT;

    SYS_DOT1AE_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_dot1ae_get_hash_field_sel(uint8 lchip, ctc_dot1ae_hash_sel_t* p_hash_sel)
{
    int32 ret = 0;
    SYS_DOT1AE_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_hash_sel);
    CTC_PTR_VALID_CHECK(p_hash_sel->field_key_list);
    CTC_MIN_VALUE_CHECK(p_hash_sel->packet_type, CTC_DOT1AE_PKT_MACSEC);
    CTC_MAX_VALUE_CHECK(p_hash_sel->packet_type, CTC_DOT1AE_PKT_MAX - 1);
    CTC_MAX_VALUE_CHECK(p_hash_sel->dir, CTC_BOTH_DIRECTION - 1);
    if (CTC_EGRESS == p_hash_sel->dir && (CTC_DOT1AE_PKT_CTCSEC_IPV4 == p_hash_sel->packet_type ||\
                                          CTC_DOT1AE_PKT_CTCSEC_IPV6 == p_hash_sel->packet_type ||\
                                          CTC_DOT1AE_PKT_CLOUDSEC_IPV4 == p_hash_sel->packet_type ||\
                                          CTC_DOT1AE_PKT_CLOUDSEC_IPV6 == p_hash_sel->packet_type))
    {

return CTC_E_INVALID_PARAM;
    }

    SYS_DOT1AE_LOCK(lchip);

    ret = MCHIP_1AE(lchip)->get_hash_field_sel?MCHIP_1AE(lchip)->get_hash_field_sel(lchip, p_hash_sel):CTC_E_NOT_SUPPORT;

    SYS_DOT1AE_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_dot1ae_add_entry(uint8 lchip, ctc_dot1ae_entry_t* p_ctc_entry)
{
    int32 ret = 0;
    SYS_DOT1AE_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_ctc_entry);
    CTC_MAX_VALUE_CHECK(p_ctc_entry->key_type, CTC_DOT1AE_KEY_MAX - 1);
    CTC_MAX_VALUE_CHECK(p_ctc_entry->dir, CTC_BOTH_DIRECTION - 1);
    SYS_DOT1AE_LOCK(lchip);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_ENTRY, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_CHANNEL, 1);
    ret = MCHIP_1AE(lchip)->add_entry?MCHIP_1AE(lchip)->add_entry(lchip, p_ctc_entry):CTC_E_NOT_SUPPORT;

    SYS_DOT1AE_UNLOCK(lchip);
    return ret;
}


int32
sys_usw_dot1ae_remove_entry(uint8 lchip, uint32 entry_id)
{
    int32 ret = 0;
    SYS_DOT1AE_INIT_CHECK(lchip);
    SYS_DOT1AE_LOCK(lchip);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_ENTRY, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_CHANNEL, 1);
    ret = MCHIP_1AE(lchip)->remove_entry?MCHIP_1AE(lchip)->remove_entry(lchip, entry_id):CTC_E_NOT_SUPPORT;

    SYS_DOT1AE_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_dot1ae_clear_stats(uint8 lchip, uint32 chan_id, uint8 an)
{
    ctc_dot1ae_stats_t stats;
    sys_dot1ae_chan_t* p_chan = NULL;
    uint32 size_an_stats = 0;
    int32 ret=0;

    SYS_DOT1AE_INIT_CHECK(lchip);
    if (DRV_IS_DUET2(lchip))
    {
        return CTC_E_NOT_SUPPORT;
    }

    /*clear hw*/
    SYS_DOT1AE_LOCK(lchip);
    if (MCHIP_1AE(lchip)->get_stats)
    {
        ret = MCHIP_1AE(lchip)->get_stats(lchip, chan_id, &stats);
        if (ret < 0)
        {
            SYS_DOT1AE_UNLOCK(lchip);
            return ret;
        }
    }
    /*clear db*/
    p_chan = _sys_usw_dot1ae_chan_lookup(lchip, chan_id);
    if (NULL == p_chan)
    {
        SYS_DOT1AE_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }
    /* clear an stats */
    size_an_stats = DRV_FROM_AT(lchip)?sizeof(sys_at_dot1ae_an_stats_t):((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip))?sizeof(sys_tmm_dot1ae_an_stats_t):sizeof(sys_tm_dot1ae_an_stats_t));
    if (DRV_FROM_TMM(lchip))
    {
        sal_memset(p_chan->an_stats, 0 , size_an_stats * MCHIP_CAP(SYS_CAP_DOT1AE_STATS_PER_CHAN));
    }
    else if (an != 0xFF)
    {
        if (an >= MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM))
        {
            SYS_DOT1AE_UNLOCK(lchip);
            return CTC_E_INVALID_PARAM;
        }
        sal_memset(&((sys_tm_dot1ae_an_stats_t*)(p_chan->an_stats))[an], 0 , size_an_stats);
    }
    else
    {
        for (an = 0; an < MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM); an++)
        {
            sal_memset(&((sys_tm_dot1ae_an_stats_t*)(p_chan->an_stats))[an], 0 , size_an_stats);
        }
    }
    /* clear global stats */
    usw_dot1ae_master[lchip]->global_stats.in_pkts_no_sci = 0;
    usw_dot1ae_master[lchip]->global_stats.in_pkts_unknown_sci = 0;

    SYS_DOT1AE_UNLOCK(lchip);
    return CTC_E_NONE;
}

int32
sys_usw_dot1ae_sync_dma_stats(uint8 lchip, void* p_data)
{
    CTC_PTR_VALID_CHECK(p_data);
    if (DRV_IS_DUET2(lchip))
    {
        return CTC_E_NOT_SUPPORT;
    }
    if (NULL == usw_dot1ae_master[lchip])
    {
        return CTC_E_NOT_INIT;
    }

    SYS_DOT1AE_LOCK(lchip);
    if (MCHIP_1AE(lchip)->sync_dma_stats)
    {
        CTC_ERROR_RETURN_WITH_UNLOCK(MCHIP_1AE(lchip)->sync_dma_stats(lchip, p_data), usw_dot1ae_master[lchip]->sec_mutex);
    }

    SYS_DOT1AE_UNLOCK(lchip);

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dot1ae_dump_db_traverse(sys_dot1ae_chan_t* p_sys_chan, void* user_data)
{
    sal_file_t p_f = NULL;
    uint32* p_index = NULL;
    sys_dot1ae_chan_bind_node_t* p_sec_chan_bind_node = NULL;
    ctc_slistnode_t        *node = NULL;
    sys_traverse_t* traversal_data = (sys_traverse_t *)user_data;
    uint8 lchip = traversal_data->value1;
    p_f = (sal_file_t)traversal_data->data;
    p_index = (uint32*)traversal_data->data1;

    if (CTC_SLISTCOUNT(p_sys_chan->bind_mem_list) || (DRV_FROM_AT(lchip)&&p_sys_chan->binded))
    {
       SYS_DOT1AE_FOREACH_DP_BEGIN(p_sys_chan->dp_bmp)
        CTC_SLIST_LOOP(p_sys_chan->bind_mem_list, node)
        {
            p_sec_chan_bind_node = _ctc_container_of(node, sys_dot1ae_chan_bind_node_t, head);
            SYS_DUMP_DB_LOG(p_f, "%-7u%-7u%-4u%-6u%-6u%-8u%-6u%-8u%-9u%-7u%-12u\n", *p_index, p_sys_chan->chan_id, p_sys_chan->dir, \
            p_sys_chan->sc_index[dp_idx], p_sys_chan->valid, p_sys_chan->include_sci, p_sys_chan->an_en, p_sys_chan->next_an, \
            p_sys_chan->an_valid, p_sys_chan->binding_type, p_sec_chan_bind_node->value);
            (*p_index)++;
        }
        if (!CTC_SLISTCOUNT(p_sys_chan->bind_mem_list)&&p_sys_chan->binded)
        {
            SYS_DUMP_DB_LOG(p_f, "%-7u%-7u%-4u%-6u%-6u%-8u%-6u%-8u%-9u%-7u%-12u\n", *p_index, p_sys_chan->chan_id, p_sys_chan->dir, \
            p_sys_chan->sc_index[dp_idx], p_sys_chan->valid, p_sys_chan->include_sci, p_sys_chan->an_en, p_sys_chan->next_an, \
            p_sys_chan->an_valid, p_sys_chan->binding_type, p_sys_chan->gport);
            (*p_index)++;
        }
        SYS_DOT1AE_FOREACH_DP_END

    }
    else
    {
        SYS_DUMP_DB_LOG(p_f, "%-7u%-7u%-4u%-6u%-6u%-8u%-6u%-8u%-9u%-7u%-12u\n", *p_index, p_sys_chan->chan_id, p_sys_chan->dir, \
        p_sys_chan->sc_index[0], p_sys_chan->valid, p_sys_chan->include_sci, p_sys_chan->an_en, p_sys_chan->next_an, \
        p_sys_chan->an_valid, p_sys_chan->binding_type, 0xFFFF);
        (*p_index)++;
    }
    return CTC_E_NONE;
}


int32
sys_usw_dot1ae_dump_db(uint8 lchip, sal_file_t p_f, ctc_global_dump_db_t* p_dump_param)
{
    int32 ret = CTC_E_NONE;
    uint32 index=0;
    sys_traverse_t user_data;
    sal_memset(&user_data, 0 , sizeof(sys_traverse_t));
    user_data.data = p_f;
    user_data.data1=(void*)&index;
     user_data.value1 = lchip;
    SYS_DOT1AE_INIT_CHECK(lchip);

    SYS_DOT1AE_LOCK(lchip);
    SYS_DUMP_DB_LOG(p_f, "%s\n", "# DOT1AE");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "{");
    SYS_DUMP_DB_LOG(p_f, "%-30s:\n", "dot1ae_sec_chan");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "-----------------------------------------------------------------------------------");
    SYS_DUMP_DB_LOG(p_f, "%-7s%-7s%-4s%-6s%-6s%-8s%-6s%-8s%-9s%-7s%-12s\n", "Index", "Chan", "Dir", "Sc_id", "Valid", "Inc_sci", "An_en", "Next_en", "An_valid", "B_type","bound");
    CTC_ERROR_GOTO(ctc_hash_traverse(usw_dot1ae_master[lchip]->chan_hash, (hash_traversal_fn)_sys_usw_dot1ae_dump_db_traverse, (void *)&user_data), ret, error_proc);
    sys_usw_opf_fprint_alloc_used_info(lchip, usw_dot1ae_master[lchip]->dot1ae_opf_type, p_f);
    SYS_DUMP_DB_LOG(p_f, "%s\n", "}");

error_proc:
    SYS_DOT1AE_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_dot1ae_init(uint8 lchip)
{
    int32  ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint16 lport = 0;
    uint32 dot1ae_enable = 0;
    uint8  gchip_id = 0;
    uint32 bypass_nh_offset = 0;
    uint32 fwd_offset = 0;
    sys_nh_param_dsfwd_t dsfwd_param;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sal_memset(&dsfwd_param, 0, sizeof(sys_nh_param_dsfwd_t));

    if (0 == SDK_WORK_PLATFORM)
    {
        ctc_chip_device_info_t dev_info;
        sal_memset(&dev_info, 0, sizeof(ctc_chip_device_info_t));
        sys_usw_chip_get_device_info(lchip, &dev_info);
        if ((dev_info.version_id == 1) && (SYS_CHIP_DEVICE_ID_USW_CTC8180 == dev_info.device_id))
        {
            return CTC_E_NONE;
        }
    }
    if (!DRV_FROM_TMM(lchip))
    {
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_DOT1AE_ENABLE, (void *)&dot1ae_enable));
        if(0 == dot1ae_enable)
        {
            return CTC_E_NONE;
        }
    }

    if (NULL != usw_dot1ae_master[lchip])
    {
        return CTC_E_NONE;
    }

    /*1.db init*/
    CTC_ERROR_GOTO(sys_usw_dot1ae_db_init(lchip), ret, ERROR_FREE);

    /*2.register init*/
    CTC_ERROR_GOTO(MCHIP_1AE(lchip)->register_init(lchip), ret, ERROR_FREE);
    if(MCHIP_1AE(lchip)->entry_hash_init)
    {
        CTC_ERROR_GOTO(MCHIP_1AE(lchip)->entry_hash_init(lchip), ret, ERROR_FREE);
    }

    if (!DRV_FROM_TMM(lchip))
    {
        if (CTC_WB_ENABLE(lchip) && CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING )
        {
            cmd = DRV_IOR(IpeUserIdCtl_t, IpeUserIdCtl_dot1AeLoopbackPtr_f);
            DRV_FIELD_IOCTL(lchip, 0, cmd, &fwd_offset);
            CTC_ERROR_RETURN(sys_usw_nh_alloc_from_position(lchip, SYS_API_NH_DSFWD, 2, fwd_offset));
        }
        else
        {
            CTC_ERROR_RETURN(sys_usw_nh_alloc(lchip, SYS_API_NH_DSFWD, 2, &fwd_offset));
        }
        /* write dsfwd */
        CTC_ERROR_GOTO(sys_usw_get_gchip_id(lchip, &gchip_id), ret, DSFWD_ERROR);
        CTC_ERROR_GOTO(sys_usw_internal_port_get_rsv_port(lchip,
                                                          SYS_INTERNAL_PORT_TYPE_WLAN_E2ILOOP, 0, &lport), ret, DSFWD_ERROR);

        dsfwd_param.dest_chipid = gchip_id;
        dsfwd_param.dest_id = lport;
        dsfwd_param.dsfwd_offset = fwd_offset;
        dsfwd_param.dsnh_offset = SYS_NH_BUILD_INT_OFFSET(SYS_DSNH4WREG_INDEX_FOR_BYPASS);

        CTC_ERROR_GOTO(sys_usw_nh_add_dsfwd(lchip, &dsfwd_param), ret, DSFWD_ERROR);

        CTC_ERROR_RETURN(sys_usw_nh_get_resolved_offset(lchip, SYS_NH_RES_OFFSET_TYPE_BYPASS_NH, &bypass_nh_offset));

        sal_memset(&dsfwd_param, 0, sizeof(sys_nh_param_dsfwd_t));

        dsfwd_param.dest_chipid = gchip_id;
        dsfwd_param.dsfwd_offset = fwd_offset + 1;
        dsfwd_param.dsnh_offset = bypass_nh_offset;

        CTC_ERROR_GOTO(sys_usw_nh_add_dsfwd(lchip, &dsfwd_param), ret, DSFWD_ERROR);

        cmd = DRV_IOW(IpeUserIdCtl_t, IpeUserIdCtl_dot1AeLoopbackPtr_f);
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &fwd_offset), ret, DSFWD_ERROR);
    }
    /*init sw*/
    CTC_ERROR_GOTO(sys_usw_dma_register_cb(SYS_CHIP_CONVERT_DMA(lchip), SYS_DMA_CB_TYPE_DOT1AE_STATS, sys_usw_dot1ae_sync_dma_stats), ret, DSFWD_ERROR);

    SYS_DOT1AE_CREATE_LOCK(lchip);
    CTC_ERROR_GOTO(sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_DOT1AE,SYS_WB_APPID_DOT1AE_SUBID_MAX, sys_usw_dot1ae_wb_sync), ret, DSFWD_ERROR);
    CTC_ERROR_GOTO(sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_DOT1AE, sys_usw_dot1ae_dump_db), ret, DSFWD_ERROR);

    if (CTC_WB_ENABLE(lchip) && CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING)
    {
        CTC_ERROR_RETURN(sys_usw_dot1ae_wb_restore(lchip));
    }
    if (CTC_WB_ENABLE(lchip))
    {
        _sys_usw_dot1ae_wb_init(lchip);
    }
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_MASTER, 1);

    /* register callback */
    CTC_ERROR_GOTO(SYS_CB_REGISTER(lchip, SYS_CB_DOT1AE_BIND_SEC_CHAN, sys_usw_dot1ae_bind_sec_chan), ret, ERROR_FREE);
    CTC_ERROR_GOTO(SYS_CB_REGISTER(lchip, SYS_CB_DOT1AE_UNBIND_SEC_CHAN, sys_usw_dot1ae_unbind_sec_chan), ret, ERROR_FREE);
    CTC_ERROR_GOTO(SYS_CB_REGISTER(lchip, SYS_CB_DOT1AE_GET_BIND_SEC_CHAN, sys_usw_dot1ae_get_bind_sec_chan), ret, ERROR_FREE);

    sys_usw_mchip_set_feature_en(lchip,CTC_FEATURE_DOT1AE);
    return CTC_E_NONE;

DSFWD_ERROR:
    if (!DRV_FROM_TMM(lchip))
    {
        sys_usw_nh_free(lchip, SYS_API_NH_DSFWD, 2, fwd_offset);
    }
    sal_mutex_destroy(usw_dot1ae_master[lchip]->sec_mutex);
ERROR_FREE :

    ctc_hash_free(usw_dot1ae_master[lchip]->chan_hash);

    if (DRV_FROM_AT(lchip))
    {
        ctc_hash_free(usw_dot1ae_master[lchip]->entry_hash);
        ctc_hash_free(usw_dot1ae_master[lchip]->pp_hash);
        if (NULL != usw_dot1ae_master[lchip]->dp0_rx_spool)
        {
            ctc_spool_free(usw_dot1ae_master[lchip]->dp0_rx_spool);
        }
        if (NULL != usw_dot1ae_master[lchip]->dp0_tx_spool)
        {
            ctc_spool_free(usw_dot1ae_master[lchip]->dp0_tx_spool);
        }
        if (NULL != usw_dot1ae_master[lchip]->dp1_rx_spool)
        {
            ctc_spool_free(usw_dot1ae_master[lchip]->dp1_rx_spool);
        }
        if (NULL != usw_dot1ae_master[lchip]->dp1_tx_spool)
        {
            ctc_spool_free(usw_dot1ae_master[lchip]->dp1_tx_spool);
        }
    }

    if(0 != usw_dot1ae_master[lchip]->dot1ae_opf_type)
    {
        sys_usw_opf_deinit(lchip, usw_dot1ae_master[lchip]->dot1ae_opf_type);
    }

    if (NULL != usw_dot1ae_master[lchip])
    {
        mem_free(usw_dot1ae_master[lchip]);
    }

    return ret;
}

int32
sys_usw_dot1ae_deinit(uint8 lchip)
{
    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    LCHIP_CHECK(lchip);
    if (NULL == usw_dot1ae_master[lchip])
    {
        return CTC_E_NONE;
    }

    /* 1. db deinit */
    sys_usw_dot1ae_db_deinit(lchip);

    /* 2. free lock */
    sal_mutex_destroy(usw_dot1ae_master[lchip]->sec_mutex);

    /* 3. free call back */
    SYS_CB_REGISTER(lchip, SYS_CB_DOT1AE_BIND_SEC_CHAN, NULL);
    SYS_CB_REGISTER(lchip, SYS_CB_DOT1AE_UNBIND_SEC_CHAN, NULL);
    SYS_CB_REGISTER(lchip, SYS_CB_DOT1AE_GET_BIND_SEC_CHAN, NULL);
    sys_usw_dma_register_cb(lchip, SYS_DMA_CB_TYPE_DOT1AE_STATS, NULL);
    sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_DOT1AE,0, NULL);
    sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_DOT1AE, NULL);
    if (DRV_FROM_AT(lchip))
    {
        CTC_ERROR_RETURN(SYS_CB_REGISTER(lchip, SYS_CB_DOT1AE_SET_HASH_TYPE, NULL));
        CTC_ERROR_RETURN(SYS_CB_REGISTER(lchip, SYS_CB_DOT1AE_GET_SECY_STATS, NULL));
    }
    /* 4. free opf*/
    sys_usw_opf_deinit(lchip, usw_dot1ae_master[lchip]->dot1ae_opf_type);

    /* 5. deinit enety hash */
    if(MCHIP_1AE(lchip)->entry_hash_deinit)
    {
        MCHIP_1AE(lchip)->entry_hash_deinit(lchip);
    }

    /* 6. deinit master*/
    mem_free(usw_dot1ae_master[lchip]);

    return CTC_E_NONE;
}


int32
sys_usw_dot1ae_lookup_entry_hash(uint8 lchip, uint32 entry_id, uint8 type, uint16* pp_bmp)
{
    sys_com_entry_hash_t* p_node = NULL;

    if(!usw_dot1ae_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_DOT1AE_LOCK(lchip);
    p_node = sys_usw_com_lookup_entry_hash(lchip, usw_dot1ae_master[lchip]->entry_hash_db, entry_id);
    if(p_node == NULL)
    {
        SYS_DOT1AE_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }
    else
    {
        *pp_bmp = p_node->pp_bmp;
    }
    SYS_DOT1AE_UNLOCK(lchip);
    return CTC_E_NONE;
}

int32
sys_usw_dot1ae_add_entry_hash(uint8 lchip, uint32 entry_id, uint16 pp_bmp, uint8 type)
{
    int32 ret = CTC_E_NONE;

    SYS_DOT1AE_INIT_CHECK(lchip);
    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_DOT1AE_LOCK(lchip);
    ret = sys_usw_com_add_entry_hash(lchip, MEM_DOT1AE_MODULE,usw_dot1ae_master[lchip]->entry_hash_db, entry_id, pp_bmp);
    SYS_DOT1AE_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_dot1ae_remove_entry_hash(uint8 lchip, uint32 entry_id)
{
    int32 ret = CTC_E_NONE;
    sys_com_entry_hash_t* p_node = NULL;

    SYS_DOT1AE_INIT_CHECK(lchip);
    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_DOT1AE_LOCK(lchip);
    p_node = sys_usw_com_lookup_entry_hash(lchip, usw_dot1ae_master[lchip]->entry_hash_db, entry_id);
    if(p_node == NULL)
    {
        ret = CTC_E_NOT_EXIST;
    }
    else
    {
        ret = sys_usw_com_remove_entry_hash(lchip, usw_dot1ae_master[lchip]->entry_hash_db, p_node);
    }
    SYS_DOT1AE_UNLOCK(lchip);
    return ret;
}


#endif
